JavaRush /Blog Java /Random-VI /Hướng dẫn về Java Microservices. Phần 3: câu hỏi chung

Hướng dẫn về Java Microservices. Phần 3: câu hỏi chung

Xuất bản trong nhóm
Dịch và điều chỉnh các vi dịch vụ Java: Hướng dẫn thực hành . Các phần trước của hướng dẫn: Hãy xem xét các vấn đề cố hữu của microservice trong Java, bắt đầu từ những thứ trừu tượng và kết thúc bằng các thư viện cụ thể. Hướng dẫn về Java Microservices.  Phần 3: câu hỏi chung - 1

Làm cách nào để làm cho một microservice Java trở nên linh hoạt?

Hãy nhớ lại rằng khi tạo vi dịch vụ, về cơ bản bạn đang giao dịch các lệnh gọi phương thức JVM để lấy các lệnh gọi HTTP đồng bộ hoặc nhắn tin không đồng bộ. Mặc dù cuộc gọi phương thức hầu hết được đảm bảo hoàn thành (ngăn chặn việc tắt JVM không mong muốn), cuộc gọi mạng theo mặc định là không đáng tin cậy. Nó có thể hoạt động, nhưng cũng có thể không hoạt động vì nhiều lý do: mạng bị quá tải, quy tắc tường lửa mới đã được triển khai, v.v. Để biết điều này tạo nên sự khác biệt như thế nào, chúng ta hãy xem ví dụ về BillingService.

Các mẫu khả năng phục hồi HTTP/REST

Giả sử khách hàng có thể mua sách điện tử trên trang web của công ty bạn. Để thực hiện việc này, bạn vừa triển khai một vi dịch vụ thanh toán có thể gọi đến cửa hàng trực tuyến của bạn để tạo hóa đơn PDF thực tế. Hiện tại, chúng tôi sẽ thực hiện lệnh gọi này một cách đồng bộ, qua HTTP (mặc dù sẽ hợp lý hơn khi gọi dịch vụ này là không đồng bộ, vì việc tạo PDF không nhất thiết phải diễn ra ngay lập tức theo quan điểm của người dùng. Chúng tôi sẽ sử dụng ví dụ tương tự trong phần tiếp theo phần và nhìn vào sự khác biệt).
@Service
class BillingService {

    @Autowired
    private HttpClient client;

     public void bill(User user, Plan plan) {
        Invoice invoice = createInvoice(user, plan);
        httpClient.send(invoiceRequest(user.getEmail(), invoice), responseHandler());
        // ...
    }
}
Tóm lại, đây là ba kết quả có thể xảy ra của lệnh gọi HTTP này.
  • OK: cuộc gọi đã thành công, tài khoản đã được tạo thành công.
  • TRÌ HOÃN: Cuộc gọi đã được thực hiện nhưng mất quá nhiều thời gian để hoàn thành.
  • LỖI. Cuộc gọi không thành công, có thể bạn đã gửi yêu cầu không tương thích hoặc hệ thống có thể không hoạt động.
Bất kỳ chương trình nào cũng phải xử lý các tình huống lỗi, không chỉ những trường hợp thành công. Điều tương tự cũng áp dụng cho microservice. Ngay cả khi bạn cần nỗ lực nhiều hơn để đảm bảo rằng tất cả các phiên bản API đã triển khai đều tương thích khi bạn bắt đầu triển khai và phát hành từng vi dịch vụ riêng lẻ. Hướng dẫn về Java Microservices.  Phần 3: câu hỏi chung - 2Một trường hợp thú vị cần xem xét là trường hợp trễ. Ví dụ: ổ cứng microservice của người phản hồi đã đầy và thay vì mất 50 ms thì phải mất 10 giây để phản hồi. Thậm chí còn thú vị hơn khi bạn gặp phải một tải nhất định đến mức tính năng không phản hồi của BillingService bắt đầu lan truyền khắp hệ thống của bạn. Để làm ví dụ minh họa, hãy tưởng tượng một nhà bếp đang dần dần bắt đầu một “khối” gồm tất cả những người phục vụ nhà hàng. Phần này rõ ràng không thể cung cấp cái nhìn tổng quan đầy đủ về chủ đề khả năng phục hồi của microservice, nhưng nó như một lời nhắc nhở cho các nhà phát triển rằng đây thực sự là vấn đề cần được giải quyết và không được bỏ qua trước khi phát hành lần đầu tiên (theo kinh nghiệm, điều này xảy ra thường xuyên hơn so với các phiên bản trước đó). không) theo sau). Một thư viện phổ biến giúp bạn suy nghĩ về độ trễ và khả năng chịu lỗi là Hystrix của Netflix. Sử dụng tài liệu của nó để đi sâu hơn vào chủ đề.

Mô hình khả năng phục hồi tin nhắn

Chúng ta hãy xem xét kỹ hơn về giao tiếp không đồng bộ. Chương trình BillingService của chúng ta bây giờ có thể trông giống như thế này, giả sử chúng ta đang sử dụng Spring và RabbitMQ để nhắn tin. Để tạo tài khoản, bây giờ chúng tôi gửi tin nhắn đến nhà môi giới tin nhắn RabbitMQ, nơi có một số công nhân đang chờ tin nhắn mới. Những nhân viên này tạo hóa đơn PDF và gửi chúng cho những người dùng thích hợp.
@Service
class BillingService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

     public void bill(User user, Plan plan) {
        Invoice invoice = createInvoice(user, plan);
        // преобразует счет, например, в json и использует его How тело messages
        rabbitTemplate.convertAndSend(exchange, routingkey, invoice);
        // ...
    }
}
Các lỗi tiềm ẩn bây giờ có vẻ hơi khác một chút vì bạn không còn nhận được phản hồi OK hoặc LỖI ngay lập tức giống như bạn đã làm với kết nối HTTP đồng bộ. Thay vào đó, chúng ta có thể có ba tình huống tiềm ẩn có thể xảy ra sai sót, điều này có thể đặt ra các câu hỏi sau:
  1. Tin nhắn của tôi có được nhân viên gửi và sử dụng không? Hay là nó bị mất? (Người dùng không nhận được hóa đơn).
  2. Có phải tin nhắn của tôi chỉ được gửi một lần? Hoặc được gửi nhiều lần và chỉ được xử lý một lần? (Người dùng sẽ nhận được nhiều hóa đơn).
  3. Cấu hình: Từ "Tôi đã sử dụng đúng khóa/tên định tuyến cho trao đổi" đến "Nhà môi giới tin nhắn của tôi có được định cấu hình và duy trì đúng cách hay hàng đợi của nó đã đầy chưa?" (Người dùng không nhận được hóa đơn).
Mô tả chi tiết về từng mẫu khả năng phục hồi vi dịch vụ không đồng bộ riêng lẻ nằm ngoài phạm vi của hướng dẫn này. Tuy nhiên, có những dấu hiệu đi đúng hướng. Hơn nữa, họ sẽ phụ thuộc vào công nghệ nhắn tin. Ví dụ:
  • Nếu bạn đang sử dụng các triển khai JMS như ActiveMQ, bạn có thể đánh đổi tốc độ để đảm bảo các cam kết hai pha (XA).
  • Nếu bạn đang sử dụng RabbitMQ, trước tiên hãy đọc hướng dẫn này, sau đó suy nghĩ kỹ về các xác nhận, khả năng chịu lỗi và độ tin cậy của thông báo nói chung.
  • Có lẽ ai đó rất thành thạo trong việc định cấu hình máy chủ Active hoặc RabbitMQ, đặc biệt là kết hợp với phân cụm và Docker (có ai không? ;))

Framework nào sẽ là giải pháp tốt nhất cho các dịch vụ vi mô Java?

Một mặt, bạn có thể cài đặt một tùy chọn rất phổ biến như Spring Boot . Nó giúp tạo tệp .jar rất dễ dàng, đi kèm với máy chủ web tích hợp như Tomcat hoặc Jetty và có thể chạy nhanh chóng ở mọi nơi. Lý tưởng để xây dựng các ứng dụng microservice. Gần đây, một cặp khung vi dịch vụ chuyên dụng, Kubernetes hoặc GraalVM , đã xuất hiện, một phần lấy cảm hứng từ lập trình phản ứng. Dưới đây là một số ứng cử viên thú vị hơn: Quarkus , Micronaut , Vert.x , Helidon . Cuối cùng, bạn sẽ phải tự mình lựa chọn, nhưng chúng tôi có thể đưa ra cho bạn một số đề xuất có thể không hoàn toàn tiêu chuẩn: Ngoại trừ Spring Boot, tất cả các khung vi dịch vụ thường được tiếp thị với tốc độ cực kỳ nhanh, gần như khởi động ngay lập tức. , chiếm ít bộ nhớ và khả năng mở rộng đến vô tận. Các tài liệu tiếp thị thường có đồ họa ấn tượng thể hiện nền tảng bên cạnh Spring Boot khổng lồ hoặc với nhau. Về lý thuyết, điều này giúp các nhà phát triển hỗ trợ các dự án cũ, đôi khi phải mất vài phút để tải. Hoặc các nhà phát triển làm việc trên đám mây muốn khởi động/dừng số lượng bộ chứa vi mô mà họ cần trong vòng 50 mili giây. Hướng dẫn về Java Microservices.  Phần 3: câu hỏi chung - 3Tuy nhiên, vấn đề là thời gian khởi động và tái triển khai kim loại trần (nhân tạo) này hầu như không đóng góp vào thành công chung của dự án. Ít nhất chúng có ảnh hưởng ít hơn nhiều so với cơ sở hạ tầng khung mạnh mẽ, tài liệu mạnh mẽ, cộng đồng và kỹ năng phát triển mạnh mẽ. Vì vậy, tốt hơn nên nhìn nó theo cách này: Nếu cho đến nay:
  • Bạn để ORM của mình chạy tràn lan, tạo ra hàng trăm truy vấn cho quy trình công việc đơn giản.
  • Bạn cần vô số gigabyte để chạy khối nguyên khối phức tạp vừa phải của mình.
  • Bạn có quá nhiều mã và độ phức tạp cao đến mức ứng dụng của bạn phải mất vài phút để tải.
Nếu đúng như vậy, thì việc bổ sung thêm các vấn đề về mycoservice (khả năng phục hồi mạng, nhắn tin, DevOps, cơ sở hạ tầng) sẽ có tác động lớn hơn nhiều đến dự án của bạn so với việc tải một Hello, world trống. Và để triển khai lại nhanh chóng trong quá trình phát triển, bạn có thể sử dụng các giải pháp như JRebel hoặc DCEVM . Hãy dành chút thời gian để trích dẫn lại Simon Brown : “ Nếu mọi người không thể xây dựng các khối nguyên khối (nhanh và hiệu quả), họ sẽ gặp khó khăn trong việc xây dựng các dịch vụ vi mô (nhanh và hiệu quả), bất kể cấu trúc .” Vì vậy, hãy chọn khung của bạn một cách khôn ngoan.

Thư viện nào phù hợp nhất cho lệnh gọi Java REST đồng bộ?

Về mặt kỹ thuật cấp thấp, bạn có thể sẽ sử dụng một trong các thư viện máy khách HTTP sau: HttpClient gốc của Java (kể từ Java 11), HttpClient của Apache hoặc OkHttp . Lưu ý rằng tôi nói "có thể" ở đây vì có các tùy chọn khác, từ máy khách JAX-RS cũ tốt đến máy khách WebSocket hiện đại . Trong mọi trường hợp, xu hướng là tạo ra một ứng dụng khách HTTP, tránh xa việc tự mình loay hoay với các cuộc gọi HTTP. Để làm điều này, bạn cần xem qua dự án OpenFeign và tài liệu của nó làm điểm khởi đầu để đọc thêm.

Các nhà môi giới tốt nhất cho tin nhắn Java không đồng bộ là gì?

Rất có thể, bạn sẽ bắt gặp ActiveMQ (Classic hoặc Artemis) , RabbitMQ hoặc Kafka phổ biến .
  • ActiveMQ và RabbitMQ là các nhà môi giới tin nhắn truyền thống, chính thức. Chúng liên quan đến sự tương tác giữa “nhà môi giới thông minh” và “người dùng ngu ngốc”.
  • Về mặt lịch sử, ActiveMQ có lợi ích là nội tuyến dễ dàng (để thử nghiệm), điều này có thể được giảm thiểu bằng cài đặt RabbitMQ/Docker/TestContainer.
  • Kafka không thể được gọi là nhà môi giới “thông minh” truyền thống. Thay vào đó, nó là một kho lưu trữ tin nhắn (tệp nhật ký) tương đối "ngu ngốc" đòi hỏi người tiêu dùng thông minh phải xử lý.
Để hiểu rõ hơn khi nào nên sử dụng RabbitMQ (hoặc các nhà môi giới tin nhắn truyền thống khác nói chung) hoặc Kafka, hãy xem bài đăng Quan trọng này làm điểm bắt đầu. Nói chung, khi chọn nhà môi giới nhắn tin, hãy cố gắng bỏ qua các lý do hiệu suất giả tạo. Đã có lúc các nhóm và cộng đồng trực tuyến liên tục tranh cãi về việc RabbitMQ nhanh như thế nào và ActiveMQ chậm như thế nào. Hiện tại, những lập luận tương tự cũng được đưa ra liên quan đến RabbitMQ, họ nói rằng nó hoạt động chậm với 20-30 nghìn tin nhắn mỗi giây. Kafka ghi lại 100 nghìn tin nhắn mỗi giây. Thành thật mà nói, những so sánh như vậy giống như so sánh sự ấm áp với sự mềm mại. Ngoài ra, trong cả hai trường hợp, giá trị thông lượng có thể ở mức thấp đến trung bình, chẳng hạn như Tập đoàn Alibaba. Tuy nhiên, bạn khó có thể gặp phải những dự án có quy mô như thế này (hàng triệu tin nhắn mỗi phút) trên thực tế. Họ chắc chắn tồn tại và họ sẽ gặp vấn đề. Không giống như 99% dự án kinh doanh Java “thông thường” khác. Vì vậy, đừng chú ý đến thời trang và cường điệu. Chọn một cách khôn ngoan.

Tôi có thể sử dụng những thư viện nào để kiểm tra vi dịch vụ?

Nó phụ thuộc vào ngăn xếp của bạn. Nếu bạn đã triển khai hệ sinh thái Spring, sẽ là điều khôn ngoan khi sử dụng các công cụ cụ thể của khung . Nếu JavaEE giống như Arquillian . Có thể đáng để xem qua Docker và thư viện Testcontainers thực sự tốt , đặc biệt giúp thiết lập cơ sở dữ liệu Oracle một cách dễ dàng và nhanh chóng cho các thử nghiệm tích hợp hoặc phát triển cục bộ. Để thử nghiệm mô phỏng toàn bộ máy chủ HTTP, hãy xem Wiremock . Để kiểm tra tính năng nhắn tin không đồng bộ, hãy thử triển khai ActiveMQ hoặc RabbitMQ, sau đó viết các bài kiểm tra bằng cách sử dụng Awaitility DSL . Ngoài ra, tất cả các công cụ thông thường của bạn đều được sử dụng - Junit , TestNG cho AssertJMockito . Xin lưu ý rằng đây không phải là một danh sách đầy đủ. Nếu bạn không tìm thấy công cụ yêu thích của mình ở đây, vui lòng đăng nó trong phần bình luận.

Làm cách nào để kích hoạt tính năng ghi nhật ký cho tất cả các vi dịch vụ Java?

Đăng nhập vào microservices là một chủ đề thú vị và khá phức tạp. Thay vì có một tệp nhật ký mà bạn có thể thao tác bằng lệnh less hoặc grep, giờ đây bạn có n tệp nhật ký và bạn muốn chúng không bị phân tán quá nhiều. Các tính năng của hệ sinh thái ghi nhật ký được mô tả rõ ràng trong bài viết này (bằng tiếng Anh). Hãy nhớ đọc nó và chú ý đến phần Ghi nhật ký tập trung từ góc độ microservices . Trong thực tế, bạn sẽ gặp nhiều cách tiếp cận khác nhau: Quản trị viên hệ thống viết một số tập lệnh nhất định thu thập và kết hợp các tệp nhật ký từ các máy chủ khác nhau thành một tệp nhật ký duy nhất và đặt chúng trên máy chủ FTP để tải xuống. Chạy kết hợp cat/grep/unig/sort trong các phiên SSH song song. Đây chính xác là những gì Amazon AWS thực hiện và bạn có thể cho người quản lý của mình biết. Sử dụng công cụ như Graylog hoặc ELK Stack (Elasticsearch, Logstash, Kibana)

Làm cách nào để các vi dịch vụ của tôi tìm thấy nhau?

Cho đến thời điểm hiện tại, chúng ta vẫn giả định rằng các vi dịch vụ của chúng ta biết về nhau và biết IPS tương ứng. Hãy nói về cấu hình tĩnh. Vì vậy, khối ngân hàng của chúng tôi [ip = 192.168.200.1] biết rằng nó cần liên lạc với máy chủ rủi ro [ip = 192.168.200.2], được mã hóa cứng trong tệp thuộc tính. Tuy nhiên, bạn có thể làm mọi thứ năng động hơn:
  • Sử dụng máy chủ cấu hình dựa trên đám mây mà từ đó tất cả các vi dịch vụ lấy cấu hình của chúng thay vì triển khai các tệp application.properties trên các vi dịch vụ của chúng.
  • Vì các phiên bản dịch vụ của bạn có thể thay đổi vị trí một cách linh hoạt, nên bạn nên xem xét các dịch vụ biết dịch vụ của bạn tồn tại ở đâu, IP của chúng là gì và cách định tuyến chúng.
  • Bây giờ mọi thứ đều năng động, các vấn đề mới nảy sinh, chẳng hạn như việc tự động bầu chọn một người lãnh đạo: chẳng hạn, ai là người chủ động thực hiện một số nhiệm vụ nhất định để không xử lý chúng hai lần? Ai thay thế người lãnh đạo khi anh ta thất bại? Việc thay thế diễn ra dựa trên cơ sở nào?
Nói chung, đây được gọi là điều phối microservice và nó là một chủ đề không đáy khác. Các thư viện như Eureka hay Zookeeper cố gắng "giải quyết" những vấn đề này bằng cách hiển thị những dịch vụ nào có sẵn. Mặt khác, chúng tạo thêm sự phức tạp. Hãy hỏi bất kỳ ai đã từng cài đặt ZooKeeper.

Làm cách nào để tổ chức ủy quyền và xác thực bằng microservice Java?

Chủ đề này cũng xứng đáng là một câu chuyện riêng biệt. Một lần nữa, các tùy chọn bao gồm từ xác thực HTTPS cơ bản được mã hóa cứng với các khung bảo mật tùy chỉnh đến chạy cài đặt Oauth2 với máy chủ ủy quyền riêng.

Làm cách nào để đảm bảo rằng tất cả môi trường của tôi trông giống nhau?

Điều đúng đối với việc triển khai không có vi dịch vụ cũng đúng đối với việc triển khai có vi dịch vụ. Hãy thử kết hợp Docker/Testcontainers và Scripting/Ansible.

Không có câu hỏi: nói ngắn gọn về YAML

Hãy tạm dừng các thư viện và các vấn đề liên quan và xem nhanh Yaml. Trên thực tế, định dạng tệp này được sử dụng làm định dạng để “viết cấu hình dưới dạng mã”. Nó cũng được sử dụng bởi các công cụ đơn giản như Ansible và những công cụ khổng lồ như Kubernetes. Để trải nghiệm sự khó khăn của việc thụt lề YAML, hãy thử viết một tệp Ansible đơn giản và xem bạn phải chỉnh sửa tệp bao nhiêu trước khi nó hoạt động như mong đợi. Và điều này mặc dù định dạng này được hỗ trợ bởi tất cả các IDE chính! Sau đó, quay lại để đọc xong hướng dẫn này.
Yaml:
  - is:
    - so
    - great

Còn các giao dịch phân tán thì sao? Kiểm tra năng suất? Chủ đề khác?

Có lẽ một ngày nào đó, trong các phiên bản tương lai của sách hướng dẫn này. Bây giờ, chỉ vậy thôi. Ở lại với chúng tôi!

Các vấn đề về khái niệm với microservice

Bên cạnh các vấn đề cụ thể của microservice trong Java, còn có những vấn đề khác, chẳng hạn như những vấn đề xuất hiện trong bất kỳ dự án microservice nào. Họ liên quan chủ yếu đến tổ chức, nhóm và quản lý.

Frontend và Backend không khớp

Frontend và Backend không khớp nhau là một vấn đề rất phổ biến trong nhiều dự án microservice. Nó có nghĩa là gì? Chỉ có điều trong các khối nguyên khối cũ, các nhà phát triển giao diện web có một nguồn cụ thể để lấy dữ liệu. Trong các dự án microservice, các nhà phát triển front-end đột nhiên có n nguồn để lấy dữ liệu. Hãy tưởng tượng rằng bạn đang tạo một loại dự án vi dịch vụ IoT (Internet of Things) nào đó trong Java. Giả sử bạn quản lý máy trắc địa và lò công nghiệp trên khắp Châu Âu. Và những lò nướng này gửi cho bạn thông tin cập nhật thường xuyên về nhiệt độ của chúng và những thứ tương tự. Sớm hay muộn bạn có thể muốn tìm lò nướng trong giao diện người dùng quản trị viên, có thể sử dụng vi dịch vụ "tìm kiếm lò nướng". Tùy thuộc vào mức độ nghiêm ngặt mà các đối tác phụ trợ của bạn áp dụng luật thiết kế theo miền hoặc vi dịch vụ, vi dịch vụ “tìm lò” chỉ có thể trả về ID lò chứ không phải các dữ liệu khác như loại, kiểu máy hoặc vị trí. Để thực hiện việc này, các nhà phát triển giao diện người dùng sẽ cần thực hiện một hoặc n lệnh gọi bổ sung (tùy thuộc vào cách triển khai phân trang) trong vi dịch vụ “lấy dữ liệu lò” với ID mà họ nhận được từ vi dịch vụ đầu tiên. Hướng dẫn về Java Microservices.  Phần 3: câu hỏi chung - 4Và mặc dù đây chỉ là một ví dụ đơn giản, được lấy từ một dự án (!) có thật, nhưng nó thậm chí còn thể hiện một vấn đề sau: siêu thị đã trở nên cực kỳ phổ biến. Đó là bởi vì với họ bạn không cần phải đi đến 10 nơi khác nhau để mua rau, nước chanh, pizza đông lạnh và giấy vệ sinh. Thay vào đó, bạn đi đến một nơi, dễ dàng hơn và nhanh hơn. Điều tương tự cũng xảy ra với các nhà phát triển front-end và microservice.

Kỳ vọng của ban quản lý

Ban quản lý có ấn tượng sai lầm rằng giờ đây họ cần thuê vô số nhà phát triển cho một dự án (tổng thể), vì giờ đây các nhà phát triển có thể làm việc hoàn toàn độc lập với nhau, mỗi người có một dịch vụ vi mô của riêng mình. Chỉ cần một chút công việc tích hợp ở giai đoạn cuối (ngay trước khi ra mắt). Hướng dẫn về Java Microservices.  Phần 3: câu hỏi chung - 5Trên thực tế, cách tiếp cận này cực kỳ có vấn đề. Trong các đoạn văn sau chúng tôi sẽ cố gắng giải thích lý do tại sao.

“Mảnh nhỏ hơn” không bằng “mảnh tốt hơn”

Sẽ là một sai lầm lớn khi cho rằng mã được chia thành 20 phần nhất thiết sẽ có chất lượng cao hơn toàn bộ một phần. Ngay cả khi chúng tôi đánh giá chất lượng từ quan điểm kỹ thuật thuần túy, các dịch vụ riêng lẻ của chúng tôi vẫn có thể chạy 400 truy vấn Hibernate để chọn người dùng từ cơ sở dữ liệu, duyệt qua các lớp mã không được hỗ trợ. Một lần nữa, chúng ta quay lại câu nói của Simon Brown: nếu bạn không xây dựng các khối nguyên khối đúng cách, sẽ rất khó để xây dựng các dịch vụ vi mô phù hợp. Nói về khả năng chịu lỗi trong các dự án microservice thường là rất muộn. Nhiều đến mức đôi khi thật đáng sợ khi thấy microservices hoạt động như thế nào trong các dự án thực tế. Lý do cho điều này là các nhà phát triển Java không phải lúc nào cũng sẵn sàng nghiên cứu khả năng chịu lỗi, kết nối mạng và các chủ đề liên quan khác ở mức độ thích hợp. Bản thân các “mảnh” nhỏ hơn nhưng “các phần kỹ thuật” lại lớn hơn. Hãy tưởng tượng nhóm microservice của bạn được yêu cầu viết một microservice kỹ thuật để đăng nhập vào hệ thống cơ sở dữ liệu, đại loại như thế này:
@Controller
class LoginController {
    // ...
    @PostMapping("/login")
    public boolean login(String username, String password) {
        User user = userDao.findByUserName(username);
        if (user == null) {
            // обработка варианта с несуществующим пользователем
            return false;
        }
        if (!user.getPassword().equals(hashed(password))) {
            // обработка неверного пароля
            return false;
        }
        // 'Ю-ху, залогинorсь!';
        // установите cookies, делайте, что угодно
        return true;
    }
}
Bây giờ nhóm của bạn có thể quyết định (và thậm chí có thể thuyết phục những người kinh doanh) rằng việc này quá đơn giản và nhàm chán, thay vì viết một dịch vụ đăng nhập, tốt hơn hết bạn nên viết một microservice UserStateChanged thực sự hữu ích mà không có bất kỳ yêu cầu kinh doanh thực tế và hữu hình nào. Và vì một số người hiện đang coi Java như một con khủng long, hãy viết microservice UserStateChanged của chúng ta bằng Erlang thời thượng. Và hãy thử sử dụng cây đỏ đen ở đâu đó, vì Steve Yegge đã viết rằng bạn phải hiểu rõ về chúng để đăng ký vào Google. Từ góc độ tích hợp, bảo trì và thiết kế tổng thể, điều này cũng tệ như viết các lớp mã spaghetti bên trong một khối duy nhất. Một ví dụ nhân tạo và thông thường? Điều này là đúng. Tuy nhiên, điều này có thể xảy ra trong thực tế.

Ít mảnh hơn - ít hiểu biết hơn

Sau đó, câu hỏi tự nhiên xuất hiện là hiểu toàn bộ hệ thống, các quy trình và quy trình công việc của nó, nhưng đồng thời, bạn, với tư cách là nhà phát triển, chỉ chịu trách nhiệm làm việc trên microservice riêng biệt của mình [95: login-101: updateUserProfile]. Nó phù hợp với đoạn trước, nhưng tùy thuộc vào tổ chức, mức độ tin cậy và giao tiếp của bạn, điều này có thể dẫn đến nhiều nhầm lẫn, nhún vai và đổ lỗi nếu có sự cố vô tình trong chuỗi vi dịch vụ. Và không có ai chịu trách nhiệm hoàn toàn về những gì đã xảy ra. Và đó hoàn toàn không phải là vấn đề thiếu trung thực. Trên thực tế, rất khó để kết nối các bộ phận khác nhau và hiểu được vị trí của chúng trong bức tranh tổng thể của dự án.

Truyền thông và dịch vụ

Mức độ giao tiếp và dịch vụ rất khác nhau tùy thuộc vào quy mô của công ty. Tuy nhiên, mối quan hệ chung là hiển nhiên: càng nhiều thì càng có nhiều vấn đề.
  • Ai điều hành microservice #47?
  • Có phải họ vừa triển khai một phiên bản microservice mới, không tương thích? Tài liệu này được ghi lại ở đâu?
  • Tôi cần nói chuyện với ai để yêu cầu một tính năng mới?
  • Ai sẽ hỗ trợ microservice đó ở Erlang sau khi người duy nhất biết ngôn ngữ này rời công ty?
  • Tất cả các nhóm vi dịch vụ của chúng tôi không chỉ làm việc bằng các ngôn ngữ lập trình khác nhau mà còn ở các múi giờ khác nhau! Làm thế nào để chúng ta phối hợp tất cả điều này một cách chính xác?
Hướng dẫn về Java Microservices.  Phần 3: câu hỏi chung - 6Điểm chính là, giống như DevOps, một cách tiếp cận chính thức đối với các dịch vụ vi mô trong một công ty lớn, thậm chí có thể là quốc tế, đi kèm với một loạt các vấn đề giao tiếp bổ sung. Và công ty phải chuẩn bị nghiêm túc cho việc này.

kết luận

Sau khi đọc bài viết này, bạn có thể cho rằng tác giả là một người phản đối kịch liệt microservices. Điều này không hoàn toàn đúng - về cơ bản tôi đang cố gắng nêu bật những điểm mà ít người chú ý đến trong cuộc chạy đua điên cuồng về công nghệ mới.

Dịch vụ vi mô hay nguyên khối?

Sử dụng microservices Java mọi lúc, mọi nơi là một điều cực đoan. Cái còn lại hóa ra giống như hàng trăm mô-đun Maven cũ tốt trong một khối nguyên khối. Nhiệm vụ của bạn là tìm sự cân bằng phù hợp. Điều này đặc biệt đúng đối với các dự án mới. Không có gì ngăn cản bạn thực hiện một cách tiếp cận “nguyên khối” thận trọng hơn và tạo ra ít mô-đun Maven tốt hơn thay vì bắt đầu với 20 dịch vụ vi mô sẵn sàng trên đám mây.

Microservices tạo thêm sự phức tạp

Hãy nhớ rằng bạn càng có nhiều vi dịch vụ và DevOps càng kém mạnh mẽ (không, việc chạy một vài tập lệnh Ansible hoặc triển khai lên Heroku không được tính!), bạn sẽ càng gặp nhiều vấn đề hơn trong quá trình này. Thậm chí chỉ cần đọc đến cuối phần hướng dẫn dành riêng cho các câu hỏi chung về vi dịch vụ Java cũng là một công việc khá tẻ nhạt. Hãy suy nghĩ kỹ về việc triển khai các giải pháp cho tất cả các vấn đề về cơ sở hạ tầng này và bạn sẽ đột nhiên nhận ra rằng vấn đề không còn là lập trình kinh doanh (những gì bạn được trả tiền để làm) mà là sửa chữa nhiều công nghệ hơn trên nhiều công nghệ hơn nữa. Shiva Prasad Reddy đã tóm tắt nó một cách hoàn hảo trong blog của mình : “Bạn không biết sẽ khủng khiếp đến thế nào khi một nhóm dành 70% thời gian vật lộn với cơ sở hạ tầng hiện đại này và chỉ còn 30% thời gian để thực hiện logic kinh doanh thực tế. ” Shiva Prasad Reddy

Có đáng để tạo các microservice Java không?

Để trả lời câu hỏi này, tôi muốn kết thúc bài viết này bằng một đoạn giới thiệu rất táo bạo, giống như một cuộc phỏng vấn của Google. Nếu bạn biết câu trả lời cho câu hỏi này từ kinh nghiệm, ngay cả khi nó dường như không liên quan gì đến vi dịch vụ, bạn có thể đã sẵn sàng tiếp cận phương pháp vi dịch vụ.

Kịch bản

Hãy tưởng tượng bạn có một khối Java chạy một mình trên máy chủ chuyên dụng Hetzner nhỏ nhất . Điều tương tự cũng áp dụng cho máy chủ cơ sở dữ liệu của bạn, nó cũng đang chạy trên máy Hetzner tương tự . Và cũng giả sử rằng khối Java nguyên khối của bạn có thể xử lý các quy trình công việc, chẳng hạn như đăng ký người dùng và bạn không tạo hàng trăm truy vấn cơ sở dữ liệu cho mỗi quy trình làm việc mà là một con số hợp lý hơn (<10).

Câu hỏi

Khối kết nối Java (nhóm kết nối) của bạn nên mở bao nhiêu kết nối cơ sở dữ liệu trên máy chủ cơ sở dữ liệu của bạn? Tại sao vậy? Bạn nghĩ khối nguyên khối của mình có thể (xấp xỉ) mở rộng được bao nhiêu người dùng hoạt động đồng thời?

Trả lời

Để lại câu trả lời của bạn cho những câu hỏi này trong phần bình luận. Tôi mong đợi tất cả các câu trả lời. Hướng dẫn về Java Microservices.  Phần 3: câu hỏi tổng quát - 8Bây giờ hãy quyết định. Nếu bạn đọc đến cuối, chúng tôi rất biết ơn bạn!
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION