أحاول إعداد عمليات التحميل إلى S3 ويبدو أن عمليات التحميل تعمل بشكل صحيح ولكن طلبات GET تفشل لسبب غريب. يبدو أن discourse يضيف “.cn” إلى URI للكائن الذي تم تحميله.
بعد تحميل الصورة في حاوية S3 الخاصة بي، يكون عنوان URL العام هو:
عندما تذكر “الإعدادات في ملف yml الخاص بك”، هل يمكنك توضيح الملف الذي تشير إليه؟ هل تتحدث ربما عن ملف app.yml الموجود في مجلد /var/discourse/containers؟
بالإضافة إلى ذلك، إذا قمت بتكوين تكامل S3/CloudFront الخاص بي مباشرة من خلال ملف YAML، فهل ستتجاوز هذه الإعدادات ما تم تكوينه في قسم المسؤول في Discourse؟
بعد إعادة بناء التطبيق باستخدام ./launcher rebuild app، عندما أزور الموقع، فإنه يعرض فقط المُحمّل دون تحميل أي شيء. عند فحص علامة التبويب “الشبكة”، وجدت أنه لا يمكنه جلب الأصول الثابتة المُجمّعة مسبقًا (معظمها .js)، والتي أفترض أنها غير موجودة في حاوية S3 الخاصة بي. يمكنك التحقق من ذلك هنا: forum.hobiguru.com.
حاولت أيضًا تشغيل مهمة الترحيل rake، ولكن دون جدوى:
root@ubuntu-s-1vcpu-1gb-fra1-01-app:/var/www/discourse# rake uploads:migrate_to_s3 --trace
** Invoke uploads:migrate_to_s3 (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute uploads:migrate_to_s3
يرجى ملاحظة أن الترحيل إلى S3 غير قابل للعكس حاليًا!
[CTRL+c] للإلغاء، [ENTER] للمتابعة
ترحيل التحميلات إلى S3 لـ 'default'...
لم يتم ترحيل بعض التحميلات إلى المخطط الجديد. يتطلب هذا الإصلاح يدويًا...
تم إلغاء المهمة!
FileStore::ToS3MigrationError: لم يكن من الممكن ترحيل بعض التحميلات إلى المخطط الجديد. تحتاج إلى إصلاح هذا يدويًا. (FileStore::ToS3MigrationError)
/var/www/discourse/lib/file_store/to_s3_migration.rb:156:in `migrate_to_s3'
/var/www/discourse/lib/file_store/to_s3_migration.rb:59:in `migrate'
/var/www/discourse/lib/tasks/uploads.rake:126:in `migrate_to_s3'
/var/www/discourse/lib/tasks/uploads.rake:106:in `block in migrate_to_s3_all_sites'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management/null_instance.rb:36:in `each_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management.rb:21:in `each_connection'
/var/www/discourse/lib/tasks/uploads.rake:104:in `migrate_to_s3_all_sites'
/var/www/discourse/lib/tasks/uploads.rake:100:in `block in <main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `block in execute'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `execute'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:188:in `invoke'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:188:in `invoke_task'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `block (2 levels) in top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `block in top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:147:in `run_with_threads'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:132:in `top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:83:in `block in run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:214:in `standard_exception_handling'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:80:in `run'
bin/rake:13:in `<top (required)>'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:58:in `load'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:58:in `kernel_load'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:23:in `run'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:455:in `exec'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/command.rb:28:in `run'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor.rb:527:in `dispatch'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:35:in `dispatch'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/base.rb:584:in `start'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:29:in `start'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/exe/bundle:28:in `block in <top (required)>'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/friendly_errors.rb:117:in `with_friendly_errors'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/exe/bundle:20:in `<top (required)>'
/usr/local/bin/bundle:25:in `load'
كان هدفي الأصلي هو استخدام S3 فقط لتخزين تحميلات المستخدمين، وأضفت CDN للتعامل مع ذلك فقط. ومع ذلك، أواجه الآن مشكلة جديدة - يتم تقديم الأصول الثابتة للتطبيق الخاص بي أيضًا عبر CDN، وهو ما لم أكن أنوي فعله.
هل هناك طريقة لتحميل جميع الأصول الثابتة عند بدء تشغيل التطبيق إلى حاوية S3 ثم تقديمها عبر CDN، أو ربما طريقة لتقديم تحميلات المستخدمين فقط عبر CDN أو هل هناك حل أفضل لهذا؟
ربما ما زلت أفتقد شيئًا واضحًا؟ لا أعرف
شكراً لمساعدتك!
في الدليل الذي تشير إليه، يوجد هذا القسم الذي يبدو ذا صلة:
DISCOURSE_CDN_URL هو شبكة توصيل محتوى (CDN) تشير إلى اسم مضيف Discourse الخاص بك وتقوم بتخزين الطلبات مؤقتًا. سيتم استخدامه بشكل أساسي للأصول القابلة للسحب: CSS وأصول السمات الأخرى.
DISCOURSE_S3_CDN_URL هو شبكة توصيل محتوى (CDN) تشير إلى حاوية تخزين الكائنات الخاصة بك وتقوم بتخزين الطلبات مؤقتًا. سيتم استخدامه بشكل أساسي للأصول القابلة للدفع: JS والصور وتحميلات المستخدم.
نوصي بأن تكون هاتان مختلفتين وأن يقوم المسؤولون بتعيين كليهما.
ومع ذلك، لست متأكدًا مما يجب تعيينه كـ DISCOURSE_CDN_URL؟ هل يجب تعيينه على نفس قيمة DISCOURSE_S3_CDN_URL: https://dsxxxxx2qn.cloudfront.net أو إنشاء مثيل CDN منفصل؟
مرحباً جيك، لست متأكداً من أنني فهمت ما تقصده بشكل صحيح. هل يمكنك توضيحه أكثر قليلاً؟
هل كنت تقصد أنه بدلاً من تعيين مستودع S3 كأصل لشبكة توصيل المحتوى (CDN) ، يجب علي تعيين نطاق forum.hobiguru.com الخاص بي كأصل؟ إذا كان الأمر كذلك ، فلا أعتقد أن هذا سيغير أي شيء لأن منتدى discourse هو الذي ينشئ تلك الروابط التي لا تؤدي إلى أي مكان ، على سبيل المثال //my-bucket-eu.my-bucket-eu/original/1X/7f242572bdb45b65ded727c13366fe490541358f.jpeg
لقد قمت بإضافة DISCOURSE_CDN_URL: https://dsuxxxhrz2qn.cloudfront.net أيضاً والآن أنتظر إعادة بناء التطبيق
لا يمكنك تسمية نطاق فرعي في ملف app.yml فقط. لا يمكن لأحد استخدامه بدون معلومات DNS مناسبة. ولأن تقديم ملفاتك يتم من AWS، يجب عليك تكوين هذا الجانب أيضًا، إذا كنت ترغب في استخدام شبكة توصيل المحتوى (CDN).
ولكن مرة أخرى. يرى المستخدمون عنوان URL الخاص بـ Disourse، إذا كانوا يريدون رؤيته. نادرًا ما يرغب أي شخص آخر غير المسؤول الإداري في القيام بشيء ما. وعمليًا لا يرى المستخدمون أبدًا عنوان URL للملفات الوسائط أو الملفات الثابتة الأخرى.
لذلك، من وجهة نظري، أنت تضيع وقتك عبثًا إذا كنت لا ترغب في استخدام شبكة توصيل المحتوى (CDN). وقد يكون ذلك ذكيًا إذا كان لديك جمهور عالمي، وبعضهم يعاني من اتصالات سيئة على مستوى الدولة.
أنا أعيش في فنلندا. لا أحصل على أي فوائد حقيقية إذا كان موقع على الجانب الآخر من العالم، في أستراليا، يستخدم شبكة توصيل المحتوى (CDN) (من خادم يقع على بعد 1000 كيلومتر مني). عنق الزجاجة الحقيقي يأتي من كيفية بناء هذا الموقع، مثل استخدامه للكثير من استدعاءات PHP غير الضرورية بدون موارد كافية.
ولكن بشكل أساسي، لا يمكنك استخدام عنوان URL cdn.example.tld دون وضع cdn على الأقل في نظام أسماء النطاقات (DNS).
في الواقع، لا أرغب في استخدام شبكة توصيل المحتوى (CDN) على الإطلاق - أريد فقط تخزين جميع تحميلات المستخدمين في S3 وتقديمها مباشرة من هناك، على الرغم من أن CloudFront هو حقًا حل أفضل من S3 مباشرة.
“لا يمكنك تسمية نطاق فرعي فقط في app.yml. لا يمكن لأحد استخدامه بدون معلومات DNS صحيحة. ولأن تقديم ملفاتك يحدث من AWS، يتعين عليك تكوين هذا الجانب أيضًا، إذا كنت تريد استخدام شبكة توصيل محتوى (CDN).”
أنا آسف، لكنني لم أفهم تمامًا ما كنت تقصده بهذه الفقرة. هل يمكنك التوضيح أكثر أو تقديم شرح؟ هل تقول إنني بحاجة إلى تكوين سجلات DNS لدلو S3 الخاص بي أو أن هناك شيئًا محددًا أحتاج إلى تعديله على جانب AWS؟
أردت المتابعة على منشوري السابق ومشاركة أنني أحرزت بعض التقدم.
ما يعمل الآن
يتم تقديم تحميلات المستخدم بشكل صحيح من مخزن S3 الخاص بي عبر شبكة توصيل المحتوى (CloudFront)، وهذا رائع!
ولكن، ما زلت أواجه مشكلة مع الأصول المترجمة مسبقًا
لم يتم تقديم الأصول المترجمة مسبقًا بشكل صحيح من شبكة توصيل المحتوى.
عندما أقوم بتعيين DISCOURSE_CDN_URL إلى عنوان URL الخاص بـ CloudFront (أي https://dsuqioxhrz2qn.cloudfront.net)، تصبح عناوين URL للأصول المترجمة مسبقًا:
المشكلة هي أن هذه المسارات غير موجودة في مخزن S3 الخاص بي. يتم تحميل الأصول المترجمة مسبقًا ضمن مجلد /assets/* في S3 (على سبيل المثال، /assets/locales، /assets/plugins، /assets/scripts)، ولكن لا يوجد مجلد /stylesheets/ وبالطبع يؤدي تحميل تلك عناوين URL إلى خطأ 403 Forbidden.
إذا قمت بتغيير DISCOURSE_CDN_URL: https://forum.hobiguru.com، فإن منتدى يعمل بشكل صحيح، ولكن الأصول يتم تقديمها الآن من الخادم (على سبيل المثال، https://forum.hobiguru.com/) وليس من شبكة توصيل المحتوى (على سبيل المثال، https://forum.hobiguru.com/stylesheets/admin_308d905aa5c03567866fec50e9a28d8721ab0463.css?__ws=forum.hobiguru.com)