2009-02-24 34 views
15

Tôi hiện đang làm việc trên một dự án j2ee đã được thử nghiệm trong một thời gian. Ngay bây giờ chúng tôi chỉ đang giải quyết một số vấn đề với quy trình triển khai. Cụ thể, có một số tệp được nhúng trong chiến tranh (một số tệp xml và .properties) cần các phiên bản khác nhau triển khai tùy thuộc vào việc bạn đang ở trong môi trường phát triển, thử nghiệm hay sản xuất. Những thứ như loglevels, hồ bơi kết nối, v.v.Làm cách nào để quản lý các tệp cấu hình và thư viện được nhúng trong ứng dụng web java?

Vì vậy, tôi đã tự hỏi cách các nhà phát triển ở đây cấu trúc quy trình của họ để triển khai các ứng dụng web. Bạn có tải nhiều cấu hình nhất có thể đến máy chủ ứng dụng không? Bạn có thay thế các tệp cài đặt theo chương trình trước khi triển khai không? Chọn một phiên bản trong quá trình xây dựng? Chỉnh sửa thủ công các cuộc chiến tranh?

Ngoài ra bạn sẽ đi bao xa trong việc cung cấp phụ thuộc thông qua thư viện tĩnh của máy chủ ứng dụng và bạn tự đặt mình vào chiến tranh bao nhiêu? Tất cả điều này chỉ để có được một số ý tưởng về những gì phổ biến (hoặc có lẽ tốt nhất) thực hành là vào lúc này.

Trả lời

6

Tôi làm việc trong môi trường có nhóm máy chủ riêng thực hiện cấu hình máy chủ QA và Sản xuất cho các ứng dụng của chúng tôi. Mỗi ứng dụng thường được triển khai trên hai máy chủ trong QA và ba máy chủ trong Sản xuất. Nhóm phát triển của tôi đã phát hiện ra rằng cách tốt nhất là giảm thiểu số lượng cấu hình cần thiết trên máy chủ bằng cách đặt nhiều cấu hình nhất có thể trong chiến tranh (hoặc tai). Điều này làm cho cấu hình máy chủ dễ dàng hơn và cũng giảm thiểu khả năng nhóm máy chủ cấu hình máy chủ không chính xác.

Chúng tôi không có cấu hình máy cụ thể, nhưng chúng tôi có cấu hình theo môi trường cụ thể (Dev, QA và Sản xuất). Chúng tôi có các tệp cấu hình được lưu trữ trong tệp chiến tranh được đặt tên theo môi trường (ví dụ: dev.properties, qa.properties, prod.properties). Chúng ta đặt một thuộc tính -D trên dòng lệnh java của máy chủ VM để xác định môi trường (ví dụ java -Dapp.env = prod ...). Ứng dụng có thể tìm thuộc tính hệ thống app.env và sử dụng nó để xác định tên của tệp thuộc tính để sử dụng.

Tôi giả sử nếu bạn có một số lượng nhỏ thuộc tính cụ thể của máy thì bạn cũng có thể chỉ định chúng làm thuộc tính -D. Commons Configuration cung cấp một cách dễ dàng để kết hợp các tệp thuộc tính với các thuộc tính hệ thống.

Chúng tôi định cấu hình các nhóm kết nối trên máy chủ. Chúng tôi đặt tên cho nhóm kết nối giống nhau cho mọi môi trường và chỉ cần trỏ các máy chủ được gán cho từng môi trường vào cơ sở dữ liệu thích hợp. Ứng dụng này chỉ phải biết tên một tên kết nối.

+0

Hầu hết các câu trả lời đều giống nhau, chấp nhận điều này vì có thể chúng tôi sẽ kết thúc một cái gì đó rất giống nhau. – wds

8

Tôi nghĩ rằng nếu các thuộc tính là máy/triển khai cụ thể, thì chúng thuộc về máy. Nếu tôi sắp xếp mọi thứ trong một cuộc chiến, nó sẽ bị bỏ qua, điều đó có nghĩa là không có gì cụ thể cho máy đang chạy. Ý tưởng này sẽ phá vỡ nếu chiến tranh có thuộc tính phụ thuộc máy trong đó.

Những gì tôi muốn làm là xây dựng một dự án với tệp properties.example, mỗi máy có một .properties sống ở đâu đó mà chiến tranh có thể truy cập nó.

Một cách khác là có nhiệm vụ kiến, ví dụ: cho chiến tranh, giai đoạn chiến tranh, chiến tranh và có các bộ phận thuộc tính của dự án, được nung trong xây dựng chiến tranh. Tôi không thích điều này nhiều vì bạn sẽ kết thúc việc có những thứ như vị trí tệp trên một máy chủ riêng lẻ như một phần của dự án xây dựng của bạn.

0

Tôi đặt tất cả cấu hình trong cơ sở dữ liệu. Vùng chứa (Tomcat, WebSphere, v.v.) cho phép tôi truy cập vào kết nối cơ sở dữ liệu ban đầu và từ đó trở đi, mọi thứ xuất phát từ cơ sở dữ liệu. Điều này cho phép nhiều môi trường, phân cụm và thay đổi động mà không có thời gian chết (hoặc ít nhất là không có triển khai lại). Đặc biệt là tốt đẹp là có thể thay đổi mức độ đăng nhập trên bay (mặc dù bạn sẽ cần hoặc là một màn hình admin hoặc một nền refresher để nhận các thay đổi). Rõ ràng điều này chỉ hoạt động đối với những thứ không cần thiết để bắt đầu ứng dụng, nhưng nhìn chung, bạn có thể vào cơ sở dữ liệu khá nhanh sau khi khởi động.

2

Tôi thường làm cho hai thuộc tính tập tin:

  • một cho chi tiết cụ thể ứng dụng (tin nhắn, nội bộ "ma thuật" từ) nhúng trong ứng dụng,
  • một cho chi tiết cụ thể môi trường (truy cập db, mức & đăng nhập đường dẫn ...) được hiển thị trên đường dẫn lớp của từng máy chủ và "được dán" (không được phân phối cùng với ứng dụng của tôi). Thông thường tôi "mavenise" hoặc "anttise" một trong những để đặt giá trị cụ thể, tùy thuộc vào mục tiêu env.
  • Những người hay sử dụng JMX để duy trì ứng dụng của họ (conf có thể được sửa đổi trong thời gian thực, mà không cần triển khai lại), nhưng nó quá phức tạp cho nhu cầu của tôi.

thư viện (tĩnh?) Server: Tôi mạnh mẽ ngăn cản máy chủ sử dụng thư viện trong các ứng dụng của tôi vì nó cho biết thêm sự phụ thuộc vào máy chủ:

  1. IMO, ứng dụng của tôi phải "tự đóng gói": thả của tôi chiến tranh, và đó là tất cả. Tôi đã thấy chiến tranh với 20 Mbs lọ trong đó, và điều đó không gây phiền toái cho tôi.
  2. Cách thực hành tốt nhất là giới hạn các phụ thuộc bên ngoài của bạn vào những gì được cung cấp bởi giáo điều J2EE: API J2EE (sử dụng Servlets, Ejbs, Jndi, JMX, JMS ...). Ứng dụng của bạn phải là "máy chủ bất khả tri".
  3. Đặt phụ thuộc vào ứng dụng của bạn (chiến tranh, tai, wathever) là tự ghi lại tài liệu: bạn biết ứng dụng của bạn tùy thuộc vào thư viện nào. Với libs của máy chủ, bạn phải ghi rõ những phụ thuộc này vì chúng ít rõ ràng hơn (và các nhà phát triển của bạn sẽ sớm quên đi chút phép thuật này).
  4. Nếu bạn nâng cấp máy chủ ứng dụng của mình, các khả năng lib máy chủ bạn phụ thuộc vào cũng sẽ thay đổi. Trình chỉnh sửa AppServer không được phép duy trì khả năng tương thích trên libs nội bộ của chúng từ phiên bản sang phiên bản (và phần lớn thời gian, chúng không).
  5. Nếu bạn sử dụng một lib được sử dụng rộng rãi được nhúng trong máy chủ ứng dụng của bạn (jakarta commons logging, aka jcl) và muốn làm xấu phiên bản của nó để nhận các tính năng mới nhất, bạn sẽ chịu rủi ro rất lớn mà máy chủ ứng dụng của bạn sẽ không hỗ trợ nó.
  6. Nếu bạn dựa vào đối tượng máy chủ tĩnh (trong trường tĩnh của lớp máy chủ, ví dụ: Bản đồ hoặc nhật ký), bạn sẽ phải khởi động lại máy chủ ứng dụng để xóa đối tượng này. Bạn mất khả năng tái triển khai lại ứng dụng của mình (đối tượng máy chủ cũ sẽ vẫn tồn tại giữa các lần triển khai lại). Sử dụng các đối tượng rộng trên toàn bộ ứng dụng (ngoài những đối tượng được J2EE định nghĩa) có thể dẫn đến các lỗi nhỏ, đặc biệt nếu đối tượng này được chia sẻ giữa nhiều ứng dụng. Đó là lý do tại sao tôi không khuyến khích sử dụng các đối tượng nằm trong một trường tĩnh của một lib của máy chủ ứng dụng.

Nếu bạn hoàn toàn cần "đối tượng này trong jar của ứng dụng này", hãy cố gắng sao chép bình trong ứng dụng của bạn, hy vọng không phụ thuộc vào bình của máy chủ khác và kiểm tra chính sách tải lớp của ứng dụng (tôi có thói quen đặt chính sách tải lớp "cha mẹ cuối cùng" trên tất cả các ứng dụng của tôi: Tôi chắc chắn tôi sẽ không bị "ô nhiễm" bởi các lọ của máy chủ - nhưng tôi không biết đó có phải là "thực hành tốt nhất" hay không.

4

tệp cấu hình wrt, tôi nghĩ câu trả lời là Steve's là tốt nhất cho đến nay. Tôi sẽ thêm gợi ý làm cho các tệp bên ngoài liên quan đến đường dẫn cài đặt của tệp chiến tranh - theo cách đó bạn có thể có nhiều cài đặt chiến tranh trong một máy chủ có các cấu hình khác nhau.

ví dụ:Nếu số dev.war của tôi được giải nén thành /opt/tomcat/webapps/dev, thì tôi sẽ sử dụng ServletContext.getRealPath để tìm thư mục cơ sở và tên thư mục chiến tranh, vì vậy, tệp cấu hình sẽ ở số ../../config/dev tương ứng với chiến tranh hoặc /opt/tomcat/config/dev cho tuyệt đối.

Tôi cũng đồng ý với Bill về cách đặt càng ít càng tốt vào các tệp cấu hình bên ngoài này. Sử dụng cơ sở dữ liệu hoặc JMX tùy thuộc vào môi trường của bạn để lưu trữ nhiều như nó có ý nghĩa. Cấu hình Apache Commons có một số nice object để xử lý các cấu hình được hỗ trợ bởi một bảng cơ sở dữ liệu.

Về thư viện, tôi đồng ý với unknown để có tất cả thư mục libs trong thư mục WEB-INF/lib trong tệp chiến tranh (tự đóng gói). Ưu điểm là mỗi lần cài đặt ứng dụng là tự trị, và bạn có thể có các bản dựng khác nhau của chiến tranh bằng cách sử dụng các phiên bản khác nhau của các thư viện đồng thời.

Điểm bất lợi là nó sẽ sử dụng nhiều bộ nhớ hơn vì mỗi ứng dụng web sẽ có bản sao riêng của các lớp, được nạp bởi trình nạp lớp của chính nó.

Nếu điều này đặt ra mối quan tâm thực sự, thì bạn có thể đặt các lọ trong thư mục thư viện chung cho thùng chứa servlet của bạn ($CATALINA_HOME/lib cho tomcat). Tất cả các cài đặt ứng dụng web của bạn đang chạy trên cùng một máy chủ phải sử dụng cùng một phiên bản của các thư viện. (Trên thực tế, điều đó không hoàn toàn đúng vì bạn có thể đặt các phiên bản ghi đè trong thư mục WEB-INF/lib riêng lẻ nếu cần, nhưng điều đó trở nên khá lộn xộn để duy trì.)

Tôi sẽ xây dựng trình cài đặt tự động cho các thư viện chung trong trường hợp này, sử dụng InstallShield hoặc NSIS hoặc tương đương với hệ điều hành của bạn. Điều gì đó có thể giúp bạn dễ dàng biết được bạn có bộ thư viện cập nhật nhất hay không và nâng cấp, hạ cấp, v.v.

Các vấn đề liên quan