كيف يمكنك إدارة ملفات التكوين المضمنة والمكتبات في Java Webapps؟

StackOverflow https://stackoverflow.com/questions/582248

سؤال

أنا أعمل حاليا على مشروع J2EE الذي كان في بيتا لفترة من الوقت الآن. الآن نحن فقط في ضرب بعض المشكلات مع عملية النشر. على وجه التحديد، هناك عدد من الملفات المضمنة في الحرب (بعض ملفات XML وبروبترات) التي تحتاج إلى إصدارات مختلفة للنشر اعتمادا على ما إذا كنت في ديف أو اختبار أو بيئة الإنتاج. أشياء مثل loglevels، تجمعات الاتصال، إلخ.

لذلك كنت أتساءل كيف يقوم المطورون هنا بتنظيم عمليةهم لنشر WebApps. هل تفريغ الكثير من التكوين قدر الإمكان إلى خادم التطبيق؟ هل تحل محل ملفات الإعدادات برمجيا قبل النشر؟ اختيار نسخة أثناء عملية البناء؟ تحرير الحروب يدويا؟

أيضا إلى أي مدى تذهب في تقديم تبعيات من خلال المكتبات الثابتة لخوادم التطبيق وكم تضع في الحرب نفسها؟ كل هذا فقط للحصول على بعض الأفكار حول ما هي الممارسة المشتركة (أو الأفضل) في الوقت الراهن.

هل كانت مفيدة؟

المحلول

أنا أعمل في بيئة حيث يقوم فريق خادم منفصل بتكوين خوادم ضمان الجودة وإنتاج التطبيقات الخاصة بنا. يتم نشر كل تطبيق بشكل عام على خادمين في ضمان الجودة وثلاث خوادم في الإنتاج. اكتشف فريق Dev الخاص بي أنه من الأفضل تقليل مقدار التكوين المطلوب على الخادم عن طريق وضع أكبر قدر ممكن من التكوين في الحرب (أو الأذن). هذا يجعل تكوين الخادم أسهل ويقلل أيضا من فرصة أن يقوم فريق الخادم بتكوين الخادم بشكل غير صحيح.

ليس لدينا تكوين خاص بالجهاز، لكن لدينا تكوين خاص بالبيئة (DEV و QA والإنتاج). لدينا ملفات التكوين المخزنة في ملف الحرب المسما عن طريق البيئة (EX. dev.properties، qa.properties، prod.properties). نضع خاصية A -D على سطر الأوامر Java Server VM لتحديد البيئة (EX. Java -Dapp.env = Prod ...). يمكن للتطبيق البحث عن خاصية نظام App.Env واستخدامه لتحديد اسم ملف الخصائص المراد استخدامه.

أفترض أنه إذا كان لديك عدد صغير من الخصائص الخاصة بالآلة، فيمكنك تحديد خصائصها كي أخرى. يوفر Commons Configuration طريقة سهلة لجمع بين ملفات الخصائص مع خصائص النظام.

نحن نقوم بتكوين تجمعات الاتصال على الخادم. نحن نسمي تجمع الاتصالات نفسها لكل بيئة وبما ببساطة توجيه الخوادم التي تم تعيينها لكل بيئة إلى قاعدة البيانات المناسبة. يجب على التطبيق فقط معرفة اسم تجمع اتصال واحد.

نصائح أخرى

أعتقد أنه إذا كانت الخصائص محددة على الجهاز / النشر، فهي تنتمي إلى الجهاز. إذا كنت سأرتل الأشياء في حرب، فينبغي أن تكون سارية، مما لا يعني شيئا خاصا بالماكة التي تعمل عليها. هذه الفكرة سوف تنكسر إذا كانت الحرب لديها خصائص تعتمد على الجهاز بها.

ما أحب القيام به هو إنشاء مشروع مع ملف خصائص. ملف مثبت عليه، كل آلة لديها .Properties التي تعيش في مكان ما يمكن للحرب الوصول إليها.

سيكون هناك طريقة بديلة هي الحصول على مهام النمل، على سبيل المثال بالنسبة لحرب Dev-War، Warb-War War ولها مجموعات من خصائص الجزء من المشروع، خبز في بناء الحرب. لا أحب ذلك كثيرا لأنك ستنتهي بإنهاء أشياء مثل مواقع الملفات على خادم فردي كجزء من بناء مشروعك.

WRT ملفات التكوين، وأعتقد ستيف الجواب هو الأفضل حتى الآن. أود أن أضيف اقتراح جعل الملفات الخارجية المتعلقة بمسار التثبيت الخاص بملف الحرب - بهذه الطريقة يمكنك الحصول على منشآت متعددة للحرب في خادم واحد مع تكوينات مختلفة.

على سبيل المثال إذا كان بلدي dev.war يحصل تفريغها في /opt/tomcat/webapps/dev, ، ثم أود استخدام ServletContext.getRealPath للعثور على المجلد الأساسي واسم مجلد الحرب، لذلك، ثم تعيش ملفات التكوين في ../../config/dev نسبة إلى الحرب، أو /opt/tomcat/config/dev لمطلق.

أنا أتفق أيضا مع مشروع قانون حول وضع أقل قدر ممكن في ملفات التكوين الخارجية هذه. باستخدام قاعدة البيانات أو JMX اعتمادا على بيئتك لتخزين أكبر قدر من المنطقي. تكوين Apache Commons لديه كائن لطيف لمعالجة التكوينات المدعومة من قبل جدول قاعدة البيانات.

فيما يتعلق بالمكتبات، وأنا أتفق مع مجهول للحصول على كل libs في WEB-INF/lib مجلد في ملف الحرب (المعبأة ذاتيا). الميزة هي أن كل تثبيت للتطبيق مستقلة، وقد يكون لديك بناء مختلف للحرب باستخدام إصدارات مختلفة من المكتبات بشكل متزامن.

العيب هو أنه سيستخدم المزيد من الذاكرة حيث سيكون لكل تطبيق ويب نسخته الخاصة من الفئات، وتحميلها بواسطة محمل الطبقة الخاصة بها.

إذا كان هذا يشكل مصدر قلق حقيقي، فيمكنك وضع الجرار في مجلد المكتبة المشترك لحاوية Servlet الخاصة بك ($CATALINA_HOME/lib ل Tomcat). جميع عمليات تثبيت تطبيق الويب الخاص بك قيد التشغيل على نفس الخادم تضطر إلى استخدام نفس إصدارات المكتبات على الرغم من. (في الواقع، هذا ليس صحيحا تماما كما يمكنك وضع إصدارات غادعة في الفرد WEB-INF/lib مجلد إذا لزم الأمر، ولكن هذا هو الحصول على فوضوي جدا للحفاظ عليها.)

أود إنشاء مثبت آلي للمكتبات الشائعة في هذه الحالة، باستخدام InstallShield أو NSIS. أو ما يعادل نظام التشغيل الخاص بك. شيء يمكن أن يجعل من السهل معرفة ما إذا كان لديك أحدث مجموعة من المكتبات، والترقية، downgrade، إلخ.

عادة ما أجري ملفين الخصائصين:

  • واحد للحصول على تفاصيل التطبيق (الرسائل، الكلمات "السحرية" الداخلية ") جزءا لا يتجزأ من التطبيق،
  • يتعارض تفاصيل البيئة الأخرى (وصول DB ومستويات السجل والمسارات ...) على كل خادم خادم وخادم "الشائكة" (لم يتم تسليمها باستخدام تطبيقي). عادة ما أكون "mavenise" أو "antress" هذه واحدة لوضع قيم محددة، اعتمادا على ENV الهدف.
  • الرجال البارد يستخدمون JMX للحفاظ على التطبيق الخاص بهم conf (يمكن تعديل conf (conf في الوقت الفعلي، دون إعادة نشر)، لكنه معقد للغاية لاحتياجاتي.

المكتبات (ثابتة؟) المكتبات: أقوم بشدة باستثناء مكتبة الخادم في تطبيقاتي لأنه يضيف التبعية إلى الخادم:

  1. IMO، يجب أن يكون تطبيقي "تعبئته ذاتيا": إسقاط حربي، وهذا كل شيء. لقد رأيت الحروب مع 20 ميغابايت من الجرار في ذلك، وهذا لا يزعجني.
  2. أفضل ممارسة شائعة هي الحد من تبعياتك الخارجية إلى ما يقدمه J2EE Docma: API J2EE (استخدام الخدمات، EJBS، JNDI، JMX، JMS ...). يجب أن يكون التطبيق الخاص بك "Agnostic Server".
  3. وضع التبعيات في التطبيق الخاص بك (الحرب والأذن، Wathever) هو توثيق الذات: أنت تعرف ما هي المكتبات التي يعتمدها تطبيقك. مع خادم Libs، عليك توثيق هذه التبعيات بوضوح لأنها أقل وضوحا (وقريبا سوف ينسى مطوروك هذا السحر القليل).
  4. إذا قمت بترقية Appserver الخاص بك، فإن الفرص التي تعتمد فيها Server Lib تعتمد عليها ستتغير أيضا. ليس من المفترض أن يحافظ محررات Appserver على التوافق على Libs الداخلية من الإصدار إلى الإصدار (ومعظم الوقت، لا).
  5. إذا كنت تستخدم Libeded Lib المضمنة على نطاق واسع في APPServer الخاص بك (تقوم Jakarta Commons بتسجيل Aka JCL، فإن AKA JCL، وتريد أن يقوم بإصدار Ugrade إنه للحصول على أحدث الميزات، فأنت تأخذ المخاطر الضخمة التي لن تدعمها Appserver.
  6. إذا كنت تعتمد على كائن خادم ثابت (في حقل ثابت لفئة الخادم، مثل خريطة أو سجل)، فسيتعين عليك إعادة تشغيل Appserver لتنظيف هذا الكائن. أنت تفقد القدرة على إعادة نشر تطبيقك الساخن (ستظل كائن الخادم القديم موجودا بين إعادة التوزيع). يمكن أن يؤدي استخدام كائنات appserver الواسعة (بخلاف تلك التي يعرفها J2EE) إلى أخطاء خفية، خاصة إذا تمت مشاركته هذا الكائن بين تطبيقات متعددة. لهذا السبب أنا قوي تثبيط استخدام الكائنات الموجودة في مجال ثابت ل appserver ليب.

إذا كنت بحاجة تماما إلى "هذا الكائن في جرة Appserver هذا"، فحاول نسخ الجرة في تطبيقك، على أمل أن لا توجد تبعية على جرة الخادم الأخرى، والتحقق من سياسة تحميل التطبيقات الخاصة بك (أتعثر على العادات لوضع عباءة "الوالد الأخير" السياسة على جميع تطبيقاتي: أنا متأكد من أنني لن أكون "ملوثا" عن طريق جرار الخادم - لكنني لا أعرف ما إذا كانت "أفضل الممارسات").

أضع كل التكوين في قاعدة البيانات. تعطيني الحاوية (Tomcat، WebSphere، ETC) الوصول إلى اتصال قاعدة البيانات الأولية ومن ثم تشغيل كل شيء من قاعدة البيانات. يسمح هذا ببيئات متعددة، التجميع، والتغييرات الديناميكية دون توقف (أو على الأقل دون إعادة نشر). لطيفة خاصة أن تكون قادرة على تغيير مستوى السجل على الطيران (على الرغم من أنك ستحتاج إما إلى شاشة مسؤول أو تنشيطي خلفية لالتقاط التغييرات). من الواضح أن هذا يعمل فقط للأشياء التي لا تحتاج إلى بدء التطبيق، ولكن بشكل عام، يمكنك الوصول إلى قاعدة البيانات بسرعة كبيرة بعد بدء التشغيل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top