خطأ في الاتصال بـ Redis الخارجي

مرحباً بالمجتمع،

لدينا إعداد Discourse في Kubernetes. نقوم بتشغيل نشر باستخدام صورة حاوية Discourse، مع استخدام Redis خارجي و PostgreSQL خارجي.
لإدارة Redis HA، قمنا بنشر 3 عقد ضمن StatefulSet مُدار بواسطة Sentinel. علاوة على ذلك، أضفنا نشر HAProxy بين Discourse و Redis بالإعداد التالي:

global
      log stdout format raw local0
      maxconn 102400
      maxsessrate 500
      maxconnrate 2000
      maxsslrate 2000

    resolvers mydns
      parse-resolv-conf
      hold valid 5s
      accepted_payload_size 8192

    defaults
      log global
      mode tcp
      timeout client 2h
      timeout connect 360s
      timeout server 2h
      default-server init-addr none
      retries 3

    frontend stats
        bind *:1024
        mode http
        http-request use-service prometheus-exporter if { path /metrics }
        stats enable
        stats uri /stats
        stats refresh 10s

    listen redis_master
      bind *:6379
      mode tcp

      option tcp-check
      tcp-check connect
      tcp-check send AUTH\ XXXXXXXXXXX\r\n

      tcp-check expect string +OK
      tcp-check send PING\r\n

      tcp-check expect string +PONG
      tcp-check send info\ replication\r\n

      tcp-check expect string role:master
      tcp-check send QUIT\r\n

      tcp-check expect string +OK
      server redis_node_0 discoursev2-redis-node-0.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1
      server redis_node_1 discoursev2-redis-node-1.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1
      server redis_node_2 discoursev2-redis-node-2.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1

    listen redis_slave
      bind *:6380
      mode tcp
      option tcp-check
      tcp-check connect
      tcp-check send AUTH\ cUvNwwd4ujTbqshTbYjeTTrX8tDlKAcYvvAUOGuk\r\n

      tcp-check expect string +OK
      tcp-check send PING\r\n

      tcp-check expect string +PONG
      tcp-check send QUIT\r\n

      tcp-check expect string +OK
      server redis_node_0 discoursev2-redis-node-0.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1
      server redis_node_1 discoursev2-redis-node-1.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1
      server redis_node_2 discoursev2-redis-node-2.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1

مشكلتنا هي أنه في كل مرة نقوم فيها بتحديث نشر Discourse، تفشل خيوط Unicorn في الاتصال بـ Redis. إنها تعيد محاولة الاتصال، وبعد بعض الوقت، تتصل جميعها في النهاية. إليكم بعض الأخطاء التي نراها في السجلات:

/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:398:in `rescue in establish_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:684:in `init_worker_process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:547:in `spawn_missing_workers'
config/unicorn.conf.rb:299:in `block in reload'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:721:in `worker_loop'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:379:in `establish_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:115:in `block in connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:295:in `reconnect'
/var/www/discourse/lib/discourse.rb:906:in `after_fork'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/bin/unicorn:128:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/bin/unicorn:25:in `<main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:344:in `with_reconnect'
E, [2024-07-24T15:42:22.524194 #531] ERROR -- : Error connecting to Redis on discoursev2-haproxy.discoursev2.svc.cluster.local:6379 (Socket::ResolutionError) (Redis::CannotConnectError)
/var/www/discourse/lib/discourse_redis.rb:217:in `reconnect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `load'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:114:in `connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:143:in `start'
I, [2024-07-24T15:42:23.499254 #422]  INFO -- : Loading Sidekiq in process id 422
2024-07-24 15:42:23 +0000: Starting Prometheus global reporter pid: 439
Booting Sidekiq 6.5.12 with Sidekiq::RedisConnection::RedisAdapter options {:host=>"discoursev2-haproxy.discoursev2.svc.cluster.local", :port=>6379, :password=>"REDACTED", :namespace=>"sidekiq"}
E, [2024-07-24T15:42:23.530765 #810] ERROR -- : Error connecting to Redis on discoursev2-haproxy.discoursev2.svc.cluster.local:6379 (Socket::ResolutionError) (Redis::CannotConnectError)
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:398:in `rescue in establish_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:115:in `block in connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:684:in `init_worker_process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:547:in `spawn_missing_workers'
/var/www/discourse/vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `<main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:344:in `with_reconnect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:295:in `reconnect'
config/unicorn.conf.rb:299:in `block in reload'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:379:in `establish_connection'
/var/www/discourse/lib/discourse.rb:906:in `after_fork'
/var/www/discourse/vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `load'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/bin/unicorn:128:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:114:in `connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:721:in `worker_loop'
/var/www/discourse/lib/discourse_redis.rb:217:in `reconnect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:143:in `start'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:143:in `start'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:344:in `with_reconnect'
config/unicorn.conf.rb:299:in `block in reload'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:398:in `rescue in establish_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:379:in `establish_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:295:in `reconnect'
/var/www/discourse/lib/discourse_redis.rb:217:in `reconnect'
E, [2024-07-24T15:42:24.540440 #887] ERROR -- : Error connecting to Redis on discoursev2-haproxy.discoursev2.svc.cluster.local:6379 (Socket::ResolutionError) (Redis::CannotConnectError)

لقد اختبرنا أيضًا إزالة HAProxy والتوجيه مباشرة إلى عقدة Redis الرئيسية، ولاحظنا نفس المشكلة. بالإضافة إلى ذلك، قمنا بتعطيل بوابة Istio بين Discourse و Redis. في كلتا الحالتين، بعد بعض الوقت، يمكن لجميع خيوط Unicorn إنشاء اتصال بـ Redis.

هل يمكن لأي شخص تقديم بعض الإرشادات حول هذه المشكلة؟ هل نحتاج إلى أي إعداد خاص على Redis؟ هذا هو إعدادنا الحالي:

appendonly yes
appendfsync no
aof-rewrite-incremental-fsync yes
save ""

أخيرًا، نود أن نعرف:

  1. ما هي الطريقة الموصى بها لوضع Redis في وضع HA؟ على حد علمنا، لا يتم دعم Redis cluster.
  2. في حالة استخدام إعداد عقدة Redis واحدة، ما هي عواقب فقدان Redis لبضع ثوانٍ؟ هل ستقوم Discourse بإعادة ملء المحتوى إذا انتقلنا إلى Redis عديم الحالة حيث يفقد كل المعلومات في كل مرة يتم إعادة تشغيله؟

شكراً جزيلاً مقدماً.

مرحباً بالمجتمع،

أردت المتابعة بشأن منشوري السابق بخصوص إعداد Discourse الخاص بنا في Kubernetes، حيث نواجه مشكلات في الاتصال بين خيوط Unicorn و Redis أثناء عمليات نشر التطبيق. على الرغم من تجربة تكوينات مختلفة، بما في ذلك إزالة HAProxy وتعطيل بوابة Istio، لا تزال المشكلة قائمة.

سنكون ممتنين للغاية لأي توجيهات أو توصيات لحل هذه المشكلة. على وجه التحديد:

  1. هل نحتاج إلى أي تكوين خاص لـ Redis لدعم إعدادنا؟
  2. ما هو النهج الموصى به لضمان التوفر العالي مع Redis، مع الأخذ في الاعتبار أن Redis Cluster غير مدعوم؟
  3. إذا اخترنا إعداد عقدة Redis واحدة، فما هو تأثير انقطاع قصير لـ Redis؟ هل سيعيد Discourse ملء البيانات في بيئة Redis عديمة الحالة حيث يتم فقدان جميع البيانات عند إعادة التشغيل؟

ستكون رؤيتك لا تقدر بثمن بينما نواصل استكشاف هذه المشكلة وإصلاحها.

شكراً مقدماً لدعمكم.