2017-11-28 43 views
5

Tôi muốn biết cách bạn chia mô-đun dự án trong java cho nguyên khối với khả năng chuyển đổi mô-đun sang các dịch vụ vi mô sau này?
đặt tên cá nhân của tôi trông như thế này:Thiết kế dự án java cho monoliths và microservices cùng một lúc

com.company.shopapp.product 
...product.domain (ddd, services, repositories, entities, aggregates, command handlers - everything with package scope) 
...product.api (everything with public scope) 
...product.controller (CQRS endpoints for commands in web perspective - (package scope)) 
...product.query(CQRS - package scope) 

com.company.shopapp.sales 
- domain 
- api 
- controller 
- query 

Những gì chúng tôi có ở đây về cơ bản là quản lý sản phẩm bối cảnh và bối cảnh doanh thu như các gói.

Mô-đun giao tiếp với nhau bằng giao diện công cộng (chỉ gói api). Trong dự án của tôi, tôi sử dụng "..api.ProductFacade" để tập trung các điểm giao tiếp.

Khi mô-đun "bán hàng" của tôi phát triển, tôi sẽ biến nó thành microservice bằng cách triển khai giao diện "..api.ProductFacade" làm ứng dụng "nghỉ ngơi" hoặc "xà phòng" và ở phía bên kia, tôi sẽ tạo Endpoint/RestController dựa trên Giao diện ProductFacade. Gói "com.company.shopapp.product.api" sẽ được chuyển thành thư viện mở rộng và được thêm vào cả hai dự án.

Chỉnh sửa: Tôi có thể đạt được điều này bằng cách sử dụng thư viện @Feign. https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html#spring-cloud-feign-inheritance

Toàn bộ ý tưởng cảm thấy dễ chịu, nhưng có thể bạn có cách tốt hơn để thiết kế dự án và đảm bảo phá vỡ nó thành dịch vụ vi mô sẽ không làm hỏng toàn bộ ứng dụng.

+0

Trên nhanh chóng của "quá rộng" resp. "có ý kiến" ... nhưng hey - câu hỏi rất thú vị! – GhostCat

+0

Có thể điều này hữu ích: https://medium.com/@wrong.about/how-to-decompose-a-system-into-modules-796bd941f036 – zapadlo

Trả lời

2

Tôi nghĩ cấu trúc mô-đun của bạn tốt. Nhưng tôi khuyên bạn nên tạo một dự án 'đa mô-đun' thực sự (link). Bằng cách này, việc sử dụng mã từ một mô-đun khác sẽ tạo ra một lỗi biên dịch . Điều này sẽ giúp bạn giữ được ý định tốt của mình!

Để làm điều này, bạn sẽ phải chia mỗi module trong một tin (triển khai) và (api, giao diện duy nhất) mô-đun công cộng (Bằng cách này, bạn không cần một 'api '-package). Mô-đun triển khai có thể phụ thuộc vào bất kỳ mô-đun công cộng nào, nhưng không phụ thuộc vào mô-đun riêng.

Nếu bạn kết nối ứng dụng của mình với nhau trong mô-đun riêng, với tiêm phụ thuộc, các mô-đun riêng sẽ không có phụ thuộc 'nội bộ'! Mô-đun riêng sẽ không có bất kỳ phụ thuộc 'biên dịch' 'nào, chỉ phụ thuộc' thời gian chạy ''.

đây nhanh chóng mô-đun phụ thuộc đồ thị: enter image description here

Tôi hy vọng bạn tìm thấy hữu ích này!

Chỉnh sửa: Bạn sẽ chỉ cần thêm mô-đun để khởi động ứng dụng!

2

TLDR: Hãy suy nghĩ linh kiện và các module riêng biệt và thiết lập "liên lạc điểm" của họ

Modules, như trong ví dụ của bạn, trông giống như cấu trúc xuyên suốt, tương ứng cũng đủ để thực hành microservice khuyến khích. Vì vậy, tất cả chúng có thể là một phần của một microservice đơn lẻ. Và nếu bạn định sử dụng DDD, bạn sẽ muốn bao gồm một tên ngữ cảnh bị giới hạn trong đường dẫn gói của bạn.

Trong mã của riêng tôi nguồn tôi thường tách (ở cấp cao nhất) mô-đun như config (để tải và phân tích, tốt, config), functional cho lõi chức năng, mô hình miền, operational để quản lý đồng thời, Akka diễn viên cấu trúc, theo dõi và như vậy, và adapters, nơi tất cả các mã API, DB và MQ đều tồn tại. Và, cuối cùng, mô-đun app, nơi tất cả được khởi chạy và giao diện bị ràng buộc để triển khai. Ngoài ra, bạn thường có một số utils hoặc commons cho bản mẫu cấp thấp hơn, các thuật toán, v.v.

Trong một số trường kiến ​​trúc, có sự tách biệt rõ ràng giữa các mô-đun và các thành phần. Trong khi trước đây là một phần của cấu trúc mã nguồn, sau đó là các đơn vị thời gian chạy, tiêu thụ tài nguyên và sống theo cách cụ thể của chúng.

Trong trường hợp của bạn, các dịch vụ nhỏ tương ứng với các thành phần như vậy. Các thành phần này có thể chạy trong cùng một JVM - và bạn nhận được một khối nguyên khối. Hoặc chúng có thể được chạy trong một JVM riêng biệt trên một máy chủ riêng biệt (có thể). Sau đó, bạn gọi chúng là microservices.

Vì vậy, bạn cần phải:

  • làm cho mã nguồn của mỗi thành phần độc lập để nó có thể được đưa ra trong một không gian thời gian chạy riêng biệt (như classloader, chủ đề, threadpool, diễn viên hệ thống cây con). Do đó, bạn cần một số phóng để đưa nó vào cuộc sống. Sau đó, bạn sẽ có thể gọi nó từ số public static void main(...) của mình.
  • giới thiệu một số mô-đun trong mã của bạn sẽ giữ ngữ nghĩa của từng thành phần riêng lẻ. Vì vậy, bạn có thể hiểu phạm vi của một thành phần từ mã.
  • giao tiếp trừu tượng giữa các thành phần, để bạn có thể sử dụng bộ điều hợp (mô-đun mã nguồn) để nói chuyện qua mạng hoặc sử dụng các cơ chế nội bộ JVM như gọi thủ tục hoặc chuyển tin nhắn của Akka.

Tôi cần lưu ý rằng ở các cấp thấp hơn, bạn có thể sử dụng các mô-đun mã nguồn chung trong các thành phần của mình, để chúng có thể có một số giao lộ trong mã. Nhưng trên mã nguồn cấp cao hơn sẽ là đặc biệt, vì vậy bạn có thể chia nó thành các mô-đun theo các thành phần.

Bạn có thể sử dụng Akka và chạy từng thành phần của bạn trong một cây con giám sát, nơi người giám sát của người phụ trách là diễn viên chính của thành phần của bạn. Sau đó, định nghĩa diễn viên chính sẽ là mô-đun chính của thành phần của bạn. Nếu bạn cần để cho các thành phần giao tiếp, bạn nên chuyển ActorRefs tương ứng cho các bộ điều hợp như một tham số cấu hình.

Bạn nói về việc tập trung các điểm giao tiếp, nhưng theo ý kiến ​​của tôi, nếu bạn quan tâm đến mô hình siêu nhỏ và mức độ tự chủ cao cho các thành phần của bạn, thì đối với mọi cuộc gọi API, ai đó phải sở hữu hợp đồng. Nhập các mẫu tương tác ngữ cảnh được giới hạn DDD khác nhau. Nếu bạn để nó trong một số module được quản lý tập trung, mà mỗi thành phần nên sử dụng, thì đó là trường hợp quản trị API. Miễn là bạn là người duy trì duy nhất, điều đó có thể thuận tiện. Nhưng khi các nhà phát triển khác nhau (hoặc thậm chí cả các nhóm) thực hiện các phần của họ, bạn sẽ cần đưa ra quyết định này một lần nữa xem xét các điều kiện mới.

Khi sau này bạn tách riêng các thành phần - sau đó bạn sẽ chuyển URL tới bộ điều hợp thay vì ActorRef.

+0

Câu trả lời rất hay! – GhostCat

2

Hệ thống vi phân theo chức năng và mức độ kết nối. tôi đã sử dụng phương pháp này:

  • com.company.product:
    • thể dịch vụ lớn:
      • cấu hình
      • dịch vụ
      • miền
      • vv
    • thể dịch vụ lớn thứ hai:
      • cấu hình
      • dịch vụ
      • miền
      • vv
    • cấu hình
    • dịch vụ // mà có thể không bao giờ được tách ra
    • miền // chung tên miền
    • e tc

Khi dự án chia bạn phân tích depencies chung mới nhìn thấy bởi bì, loại trừ thư viện chung, sao chép dự án cho mỗi microservice, xóa mã không cần thiết, có lẽ thay đổi việc triển khai dịch vụ (ví dụ, nếu "có thể dịch vụ lớn" sử dụng "dịch vụ lớn thứ hai có thể có"), cấu hình và xây dựng. "Lớn" trong ngữ cảnh đó có nghĩa là thực hiện chức năng chính thức của một cái gì đó, những gì có thể được thu nhỏ theo chiều ngang, hoặc cần phải được microservice vì lý do khác.

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