2009-09-21 67 views
31

Chúng tôi có hệ thống Java lớn (> 500.000 LOC) phụ thuộc vào gói 40-50 OSS . Hệ thống được xây dựng với Ant và quản lý phụ thuộc là được xử lý thủ công hiện tại. Tôi đang điều tra Ivy và/hoặc Maven để tự động phụ thuộc. Chúng tôi đã xem Maven như một hệ thống tự động hóa xây dựng năm ngoái và từ chối nó bởi vì nó sẽ yêu cầu hoàn toàn tái cơ cấu hệ thống của chúng tôi để phù hợp với kiến ​​trúc của Maven. Bây giờ tôi đang tìm cách tự động hóa các tác vụ quản lý phụ thuộc.Quản lý phụ thuộc hệ thống Java lớn

Tôi đã thực hiện một số thử nghiệm với Ivy nhưng đã gặp sự cố. Ví dụ: khi tôi chỉ định ActiveMQ làm phụ thuộc và cho Ivy biết sử dụng POM trong kho lưu trữ Maven để biết đặc điểm phụ thuộc, Ivy truy xuất một loạt gói (Jetty, Derby và Geronimo cho ví dụ ) mà tôi biết aren ' t cần thiết để chỉ sử dụng ActiveMQ.

Nếu tôi đặt usepoms = "false" trong ivysettings.xml rồi nó lấy chỉ activemq.jar, nhưng điều đó dường như đánh bại mục đích của Ivy và relegates nó vào một jar-fetcher đơn giản với tay xây dựng phụ thuộc thông số kỹ thuật .

Có vấn đề lớn hơn ở đây, những gì thường được gọi là "DLL Hell" trong Windows. Trong một số trường hợp, hai phụ thuộc cấp đầu tiên trực tiếp sẽ trỏ đến các phiên bản khác nhau của cùng một phụ thuộc chuyển tiếp (đối với instance log4j.jar). Chỉ có một log4j.jar có thể ở trong classpath, do đó, độ phân giải phụ thuộc liên quan đến việc xác định phiên bản nào là tương thích với tất cả các máy khách trong hệ thống của chúng tôi.

Tôi đoán là tất cả đều có chất lượng phụ thuộc của từng gói đặc điểm kỹ thuật (POM). Trong trường hợp ActiveMQ, không có phạm vi khai báo , vì vậy mọi tham chiếu đến ActiveMQ sẽ tải xuống tất cả các phụ thuộc của chúng tôi trừ khi chúng tôi loại trừ một cách thủ công những gì chúng tôi biết chúng tôi không muốn.

Trong trường hợp của log4j, độ phân giải phụ thuộc tự động sẽ đòi hỏi rằng tất cả các khách hàng log4j của (các gói khác phụ thuộc vào log4j) xác nhận đối với tất cả các phiên bản trước của log4j và cung cấp một phạm vi (hoặc list) của các phiên bản log4j tương thích trong POM. Đó có thể là quá nhiều điều để hỏi.

Đây có phải là trạng thái hiện tại của sự cố hay tôi thiếu gì đó không?

+8

+1 để mô tả rõ ràng vấn đề với các giải pháp đã thử. Tôi hy vọng bạn nhận được câu trả lời hay. –

+2

4 câu trả lời được bình chọn hàng đầu đều cung cấp góc nhìn có giá trị. Kevin là ngắn gọn và chính xác. Robert và Rich cung cấp nhiều chi tiết hơn. Vladimir đóng góp một ý kiến ​​tích cực dựa trên kinh nghiệm thực tế. Cả bốn cùng nhau giúp tôi đặt ra kỳ vọng của mình và chỉ ra cách giải quyết vấn đề. Tôi muốn "chấp nhận" tất cả bốn câu trả lời, nhưng SO không cho phép điều đó. Tôi cho phép Robert Munteanu chấp nhận vì anh ta là người đầu tiên trả lời chi tiết. –

Trả lời

11

Bạn đang hoàn toàn đúng khi nói rằng

Tôi đoán tất cả sẽ tóm tắt chất lượng của đặc tả phụ thuộc của mỗi gói (POM).

Điều duy nhất tôi muốn thêm là xem POM hoặc bất kỳ dạng siêu dữ liệu nào khác, làm điểm bắt đầu. Nó khá hữu ích, ví dụ: ActiveMQ cung cấp tất cả các phụ thuộc cho bạn, nhưng nó tùy thuộc vào bạn để lựa chọn nếu nó thực sự phù hợp với dự án của bạn.

Sau khi tất cả, ngay cả khi đưa phiên bản log4j vào tài khoản, bạn sẽ có một phụ thuộc bên ngoài chọn phiên bản hoặc chọn phiên bản bạn biết làm việc cho bạn?


Đối với làm thế nào bạn có thể chọn để phụ thuộc thợ may, đây là những gì bạn có thể làm với Ivy:

gói không cần thiết

Ivy lấy một loạt các gói (Jetty, Derby và Geronimo cho ví dụ) mà tôi biết là không cần thiết để chỉ sử dụng ActiveMQ.

Điều này thường xảy ra do mô đun kém trong ứng dụng. Một số phần của ứng dụng cần Jetty chẳng hạn, nhưng bạn kết thúc với sự phụ thuộc transitive này ngay cả khi bạn không sử dụng nó.

Bạn có thể muốn nhìn vào ivy exclude mechanism:

<dependency name="A" rev="1.0"> 
    <exclude module="B"/> 
</dependency> 

phiên bản phụ thuộc

Chỉ có một log4j.jar có thể trong classpath, vì vậy phụ thuộc độ phân giải bao gồm việc tự xác định phiên bản nào là phù hợp với tất cả các khách hàng của nó trong hệ thống của chúng tôi.

Có lẽ tôi đang hiểu sai điều này, nhưng không có yếu tố thủ công trong giải quyết xung đột của Ivy. Có một danh sách các default conflict managers:

  • tất cả: này mâu thuẫn xung đột quản lý quyết tâm bằng cách chọn tất cả các phiên bản. Còn được gọi là NoConflictManager, nó loại bỏ bất kỳ mô-đun nào.
  • thời gian mới nhất: người quản lý xung đột này chỉ chọn bản sửa đổi 'mới nhất', mới nhất được xác định là mới nhất trong thời gian. Lưu ý rằng thời gian gần đây nhất là tốn kém để tính toán, vì vậy, bạn nên sửa đổi phiên bản mới nhất nếu có thể.
  • bản xem lại mới nhất: người quản lý xung đột này chỉ chọn bản sửa đổi 'mới nhất', mới nhất được xác định bằng so sánh chuỗi các bản sửa đổi.
  • tương thích mới nhất: người quản lý xung đột này chọn phiên bản mới nhất trong các xung đột có thể dẫn đến một nhóm phụ thuộc tương thích. Điều này có nghĩa là cuối cùng, người quản lý xung đột này không cho phép bất kỳ xung đột nào (như người quản lý xung đột nghiêm ngặt), ngoại trừ việc nó theo một chiến lược nỗ lực tốt nhất để tìm một tập hợp các mô-đun tương thích (theo các ràng buộc phiên bản);
  • nghiêm ngặt: người quản lý xung đột này ném ngoại lệ (tức là gây ra lỗi xây dựng) bất cứ khi nào xung đột được tìm thấy.

Nếu cần, bạn có thể provide your own conflict manager.

-5

"Đây có phải là hiện trạng của vấn đề"

Yes.

Đây là sự cân bằng mã nguồn mở.

Một khung nguồn đóng (tức là .Net) sẽ giải quyết tất cả điều này cho bạn.

Giải pháp nguồn mở có nghĩa là bạn phải giải quyết nó (và giải quyết) mọi lúc.

Bạn có thể tìm thấy một số cấu hình được tạo sẵn và trả tiền cho ai đó để cập nhật những cấu hình đó. Ví dụ, bạn có thể chọn sử dụng Red Hat Enterprise Linux. Nếu bạn dính vào chính xác những gì họ hỗ trợ (và không có gì nhiều hơn) thì cấu hình được giải quyết.

Tỷ lệ cược là tốt, tuy nhiên, không có cấu hình đóng gói nào đáp ứng các yêu cầu của bạn.

+2

Tôi mạnh mẽ không đồng ý với nguồn đóng của bạn là tốt hơn, nguồn mở đang nỗ lực đầu tư liên tục. Bạn có một giải pháp thay thế nguồn đóng cho vấn đề này không? Ngoại trừ .NET. –

+1

Tôi không đồng ý rằng đây là trạng thái của các vấn đề. Các phụ thuộc trong câu hỏi là tùy chọn và được quản lý đúng trong Maven (xem câu trả lời của tôi để biết thêm chi tiết). Có thể là Ivy không thể đối phó với tài sản tùy chọn, nhưng nó vẫn có một phương tiện để đối phó với những phụ thuộc đó. Vậy cơ sở của bạn để đưa ra yêu cầu này là gì? –

+0

@Robert Munteanu: Tôi không nói rằng một giải pháp nguồn đóng tốt hơn trong một cách chăn mền mơ hồ. Nó cung cấp các thành phần được tích hợp sẵn. Đó là * chỉ * lợi thế. Và hầu hết thời gian, đó thực sự là một trách nhiệm bởi vì các công cụ được tích hợp sẵn phát triển chậm và chậm lại phía sau nhà nước của nghệ thuật. –

4

Tôi nghĩ đây thực sự là trạng thái hiện tại của các vấn đề. OSGi và hệ thống đóng gói mới được đề xuất cho java 1.7 (có thảo luận về điều đó đã đi đến kết luận chưa?) Đang cố gắng khắc phục ít nhất vấn đề tùy thuộc vào từng phiên bản khác nhau của thư viện, nhưng tôi không nghĩ rằng họ sẽ có thể khắc phục sự cố của bạn ngay bây giờ.

+0

bạn có bất kỳ liên kết nào có thêm thông tin về "hệ thống đóng gói mới được đề xuất cho java 1.7" không? –

+0

Tôi đã suy nghĩ về JSR 277: http://jcp.org/en/jsr/detail?id=277 - google cho rất nhiều ý kiến ​​;-) ... Tôi nghĩ rằng điều này có nghĩa là để đi vào 1.7 nhưng dường như nó sẽ không xảy ra. –

2

"Đây có phải là trạng thái hiện tại của sự cố không?"

Không có OSGi. Bạn có thể muốn xem các gói và gói OSGi. Một gói giống như một tệp jar, nhưng nó hỗ trợ siêu dữ liệu chi tiết phiên bản của nó và các phiên bản của các gói liên quan mà nó yêu cầu (bằng cách đặt các thuộc tính trong tệp META-INF). Vì vậy, gói log4j của bạn sẽ cho biết phiên bản của nó và các gói phụ thuộc sẽ trình bày chi tiết những phiên bản nào của log4j mà chúng yêu cầu.

Hơn nữa, cơ chế trình nạp lớp không phân cấp được hỗ trợ, sao cho bạn có thể tải nhiều phiên bản của log4j và các gói khác nhau có thể chỉ định và liên kết với các phiên bản khác nhau đó.

Javaworld có phần giới thiệu rất hay here.

5

Thats khá nhiều. Hệ thống phụ thuộc maven (mà Ivy nhiều hơn hoặc ít hơn sau) để nó lên đến các dự án riêng lẻ để làm tốt công việc bổ sung dữ liệu meta cần thiết cho các phụ thuộc của chúng. Hầu hết là không.

Nếu bạn đi theo tuyến đường đó, hãy dành thời gian thiết lập loại trừ.

Để các áp phích giới thiệu OSGi, OP nói rằng ông không phải là sẵn sàng để tái kiến ​​trúc sư xây dựng hệ thống của mình cho Maven, tôi sẽ không nghĩ anh ấy sẽ muốn tái kiến ​​trúc sư ứng dụng của mình là OSGi tuân thủ. Bên cạnh đó, rất nhiều dự án OSS có OSGi compliant (và không có như nhiều như bạn muốn hy vọng) có dữ liệu meta là xấu hoặc tồi tệ hơn trong Maven

+0

Tôi nghĩ rằng nói "Hầu hết không" là một cường điệu tổng, bạn có thể trích dẫn bất kỳ dự án lớn nào được cấu hình kém không? Phần lớn các dự án Maven mà tôi đã sử dụng đều cư xử tốt. Nó là nhiều hơn trường hợp mà hầu hết người dùng không hiểu tất cả các sắc thái của hệ thống và nhận được tripped lên của họ. Nó vẫn có thể là một vấn đề nếu người dùng không RTFM, nhưng đó luôn là trường hợp với các hệ thống phức tạp. –

+0

Ivy không "chủ yếu làm theo" hệ thống phụ thuộc Maven, nó chỉ có một hệ thống bộ điều hợp cho nó. Đúng, POM được nhập khẩu từ Maven sẽ rất khó nhưng nếu bạn dành thời gian để tự làm lại các thiết lập phụ thuộc cho Ivy, bạn thực sự kết thúc với một thứ Maven tốt hơn có thể cung cấp. – Esko

+0

@Rich Khác với ActiveMQ mà OP ghi nhận? Tôi đã gặp sự cố với CXF không khai báo phụ thuộc đúng cách là "tùy chọn" hoặc không cần thiết. – Kevin

5

Trong danh sách phụ thuộc bạn liệt kê, các điều sau được định nghĩa là optional trong số activemq-core pom (cũng xem relevant section từ sách Maven).

  • org.apache.derby: derby
  • org.apache.geronimo.specs: geronimo-jta_1.0.1B_spec

Tôi không thấy một sự phụ thuộc trực tiếp vào Jetty, vì vậy nó có thể được bao gồm quá mức từ một trong các phụ thuộc tùy chọn.

Trong phụ thuộc tùy chọn Maven được xử lý tự động. Về cơ bản bất kỳ phụ thuộc nào được khai báo tùy chọn phải được redeclared trong pom của bạn cho nó được sử dụng.Từ tài liệu được liên kết ở trên:

Phụ thuộc tùy chọn được sử dụng khi không thực sự có thể (vì bất kỳ lý do gì) để chia dự án thành các mô-đun phụ. Ý tưởng là một số phụ thuộc chỉ được sử dụng cho các tính năng nhất định trong dự án và sẽ không cần thiết nếu tính năng đó không được sử dụng. Lý tưởng nhất, một tính năng như vậy sẽ được chia thành một mô-đun phụ phụ thuộc vào dự án lõi ... tiểu dự án mới này sẽ chỉ có các phụ thuộc không tùy chọn, vì bạn cần tất cả nếu bạn quyết định sử dụng chức năng của tiểu dự án.

Tuy nhiên, vì dự án không thể tách rời được (một lần nữa, vì bất kỳ lý do gì), những phụ thuộc này được khai báo tùy chọn. Nếu người dùng muốn sử dụng chức năng liên quan đến sự phụ thuộc tùy chọn, họ sẽ phải redeclare rằng phụ thuộc tùy chọn trong dự án của riêng họ. Đây không phải là cách rõ ràng nhất để xử lý tình huống này, nhưng sau đó lại cả hai phụ thuộc tùy chọn và loại trừ phụ thuộc là các giải pháp khoảng trống.

Tôi không chắc liệu bạn có thể định cấu hình Ivy để bỏ qua các phụ thuộc tùy chọn, nhưng bạn có thể định cấu hình nó thành exclude dependencies. Ví dụ:

<dependency name="A" rev="1.0"> 
    <exclude module="B"/> 
</dependency> 

Điều này hoàn toàn không thỏa đáng mà tôi biết. Nó có thể là Ivy không hỗ trợ phụ thuộc tùy chọn (tôi sẽ có một cái nhìn sâu hơn và cập nhật nếu tôi tìm thấy bất cứ điều gì), nhưng cơ chế loại trừ ít nhất cho phép bạn quản lý chúng.


Về phần cuối cùng của câu hỏi của bạn. Maven sẽ giải quyết các phiên bản phụ thuộc cho log4j và nếu các phiên bản tương thích, nó sẽ tự động chọn 'gần nhất' của các phiên bản được liệt kê.

Từ Introduction to the Dependency Mechanism:

  • phụ thuộc hòa giải - điều này xác định những gì phiên bản của một phụ thuộc sẽ được sử dụng khi có nhiều phiên bản của một vật đang gặp phải. Hiện tại, Maven 2.0 chỉ hỗ trợ bằng cách sử dụng "định nghĩa gần nhất" có nghĩa là nó sẽ sử dụng phiên bản của sự phụ thuộc gần nhất cho dự án của bạn trong cây phụ thuộc. Bạn luôn có thể đảm bảo một phiên bản bằng cách khai báo nó một cách rõ ràng trong POM của dự án của bạn. Lưu ý rằng nếu hai phiên bản phụ thuộc ở cùng độ sâu trong cây phụ thuộc, cho đến khi Maven 2.0.8 không được xác định cái nào sẽ thắng, nhưng vì Maven 2.0.9 là thứ tự trong khai báo đếm: khai báo đầu tiên sẽ thắng.

    • "định nghĩa gần nhất" có nghĩa là phiên bản được sử dụng sẽ là phiên bản gần nhất với dự án của bạn trong cây phụ thuộc, ví dụ: nếu phụ thuộc cho A, B và C được định nghĩa là A -> B -> C -> D 2.0 và A -> E -> D 1.0, thì D 1.0 sẽ được sử dụng khi xây dựng A vì đường dẫn từ A đến D qua E ngắn hơn. Bạn rõ ràng có thể thêm một phụ thuộc vào D 2.0 A để buộc việc sử dụng D 2,0

Trường hợp các phiên bản không tương thích bạn gặp rắc rối lớn hơn độ phân giải phụ thuộc. Tôi tin rằng Ivy hoạt động trên một mô hình tương tự nhưng tôi không có chuyên gia.

3

Tôi hiện đang sử dụng Ivy để quản lý hơn 120 thư viện OSS và độc quyền cho một số dự án (một số độc lập, một số người phụ thuộc). Trở lại năm 2005 (khi Ivy vẫn còn từ Jayasoft), tôi đã quyết định (hoặc phải) viết các tệp ivy.xml cho mỗi gói tích hợp.

Lợi thế lớn nhất là tôi có toàn quyền kiểm soát các cấu hình khác nhau. Điều này nghe có vẻ quá mức cần thiết nhưng một số hệ thống xây dựng của chúng tôi đã hoạt động đáng tin cậy hơn 4 năm nay và việc thêm một thư viện mới thường là một công việc 5 phút.

0

Có toàn bộ ý tưởng về tiêm phụ thuộc - luôn luôn dẫn đến chương trình cần phải được tái cơ cấu. Tôi đã nghe một số tiếng ồn về GUICE là tốt trong lĩnh vực này. Trong quan điểm triển khai, tôi đã có được thành công hợp lý với việc triển khai chỉ .jar chúng tôi xây dựng với các phụ thuộc .jars được lấy từ các dự án gốc thông qua jnlp. Hệ thống xây dựng đằng sau việc này liên quan đến việc theo dõi thủ công các phiên bản mới của các phụ thuộc và cập nhật trong hệ thống xây dựng.

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