Tại sao việc chia sẻ giao diện giữa máy chủ và máy khách lại là một ý tưởng tồi như vậy?


12

Tôi đang đọc tài liệu Spring Cloud Netflix khi tôi tìm hiểu về cách chia sẻ giao diện giữa máy chủ HTTP và máy khách của nó. Họ sử dụng ví dụ này cho microservice, mặc dù không có lý do nào khiến nó không thể mở rộng sang giao tiếp HTTP chung:

// The shared interface, in a common library
public interface UserService {
    @RequestMapping(method = GET, value = "/users/{id}")
    User getUser(@PathVariable long id);
}

// The controller, on the server
@RestController
public class UserResource implements UserService {
}

// The same interface used for the client
@FeignClient("users")
public interface UserClient extends UserService {
}

Điều này xác định một giao diện được sử dụng cho cả máy chủ (Spring @RestControllerbiến nó thành máy chủ HTTP) và máy khách (Fict @FeignClientthiết lập giao diện đó cho việc sử dụng máy khách HTTP). Việc triển khai lớp máy chủ và máy khách có thể được sử dụng trong các dự án riêng biệt nhưng vẫn sử dụng cùng một giao diện để đảm bảo rằng các loại khớp với nhau.

Tuy nhiên, bên dưới ví dụ họ đặt cảnh báo sau:

Lưu ý: Thông thường không nên chia sẻ giao diện giữa máy chủ và máy khách. Nó giới thiệu khớp nối chặt chẽ và thực tế cũng không hoạt động với Spring MVC ở dạng hiện tại (ánh xạ tham số phương thức không được kế thừa).

OK, vì vậy nó không được tích hợp tốt ngay bây giờ ... nhưng phần đó xuất hiện sau cảnh báo chống lại việc chia sẻ mã và giới thiệu khớp nối giữa máy chủ và máy khách, điều mà họ cho là quan trọng hơn. Tại sao họ nghĩ rằng đó là một ý tưởng tồi để chia sẻ một giao diện theo cách này?

Không có nó, bạn sẽ mất khả năng đảm bảo rằng máy chủ và máy khách gửi cho nhau dữ liệu mà cả hai có thể hiểu được. Bạn có thể thêm một trường vào một nhưng không phải trường khác và chỉ khám phá sự không phù hợp cho đến khi thời gian chạy. Theo suy nghĩ của tôi, nó không giới thiệu khớp nối, mà chỉ tiết lộ khớp nối đã tồn tại. Có phải nhu cầu làm cho máy chủ hoàn toàn độc lập lớn hơn nhu cầu cho họ biết loại dữ liệu nào họ sẽ nhận được không?


1
Khớp nối tồn tại, về mặt dữ liệu / định dạng được xử lý bởi máy khách / máy chủ, được xác định bởi giao thức - một phần tài liệu có thể được sử dụng như một quy ước . Khớp được giới thiệu bằng cách chia sẻ giao diện là khớp nối thời gian biên dịch - xem xét điều gì xảy ra khi giao diện bị thay đổi (ví dụ, theo cách không tương thích ngược), nhưng mã máy khách / máy chủ sử dụng giao diện đó được triển khai vào các thời điểm khác nhau. Việc ghép thời gian triển khai đó có thể khó quản lý hơn, đặc biệt là ở quy mô của Netflix.
Castaglia

1
Tôi khá chắc chắn rằng tôi không hoạt động ở quy mô của Netflix :) nhưng nếu các giao diện được thay đổi theo cách không tương thích ngược , thì điều này không chỉ chuyển lỗi từ được tìm thấy tại thời gian biên dịch sang thời gian chạy thay thế? Họ có cho rằng không sao khi để một vài cuộc gọi chức năng thất bại trong khi họ từ từ nâng cấp tất cả các máy chủ?
Ben S

1
Có khả năng; phụ thuộc vào mã khách hàng Cũng xem xét trường hợp khác: các máy chủ được nâng cấp trước và khách hàng phải xử lý các cuộc gọi thất bại (bất ngờ) ...
Castaglia

1
Chỉ tò mò, bằng cách chia sẻ giao diện này, nó có giới hạn ngôn ngữ / ngăn xếp nào bạn có thể xây dựng ứng dụng khách không?
JeffO

Có - đó là tệp Java nên bạn sẽ phải sử dụng Java. Bạn thể sử dụng ngôn ngữ JVM khác nhưng tôi chưa thử.
Ben S

Câu trả lời:


6

Lý do như đã nêu trong các bình luận là nó dẫn đến việc kết hợp chặt chẽ nền tảng máy khách của bạn với nền tảng máy chủ của bạn. Ở đây, điều đó có nghĩa là khách hàng của bạn được yêu cầu sử dụng ngôn ngữ / nền tảng bạn đang sử dụng trên máy chủ để hiểu hợp đồng dự kiến ​​của máy chủ của bạn. Lưu ý rằng có một sự khác biệt giữa việc chia sẻ cùng một mã (một tạo tác của ngôn ngữ / nền tảng cụ thể) và đồng ý về một hợp đồng cụ thể.

Nhiều dự án thay vì sử dụng tài liệu cho hợp đồng của họ. Ví dụ yêu cầu và phản hồi ở định dạng trung tính (ví dụ JSON) trên các giao thức chuẩn (ví dụ REST). (Xem tài liệu API Stripe chẳng hạn). Bởi vì việc viết hợp đồng dựa trên mã cho mọi nền tảng khách hàng có thể bạn muốn sử dụng hoặc cho phép là không thực tế. Vẫn còn những người khác sử dụng các công cụ quản lý API để xác định các hợp đồng trung lập .

Ví dụ của bạn về việc thêm một trường là một mối quan tâm riêng biệt - một ví dụ về lý do tại sao nó quan trọng đối với các hợp đồng API phiên bản. Hãy để khách hàng sử dụng phiên bản mà họ được thiết kế. Phiên bản API mới không tương thích ngược tồn tại cùng với phiên bản cũ. Ứng dụng khách cho phiên bản cũ tiếp tục hoạt động cho đến khi nhóm của nó bắt đầu cập nhật hoặc cho đến khi bạn nghỉ hưu phiên bản cũ (sau thời gian khấu hao / di chuyển). Xem Thay đổi song song .

Thực hiện theo cảnh báo (lời khuyên ngầm trong) giúp khách hàng và máy chủ phát triển theo cách và nhịp độ có ý nghĩa đối với từng người. Nếu bạn có thể đảm bảo một cách hợp lý rằng máy chủ và máy khách của bạn sẽ luôn chia sẻ cùng một ngôn ngữ / nền tảng VÀ phát triển theo cùng một tốc độ, thì việc sử dụng một mã tạo ngôn ngữ dành riêng cho ngôn ngữ và nền tảng vì hợp đồng của bạn có thể sẽ ổn. Tuy nhiên, điều này có lẽ không phải là một kỳ vọng hợp lý, đặc biệt là đối với các dự án nhắm mục tiêu Netflix OSS (thứ gì đó đặc biệt hướng đến khả năng mở rộng và hiệu suất của đám mây, với tất cả sự phức tạp cần thiết đó).


2
Là khách hàng thực sự mong đợi để sử dụng giao diện? Tôi đã luôn xem các cấu trúc như vậy là một cách để làm cho việc viết một khách hàng dễ dàng hơn. Sau tất cả, bạn vẫn có thể viết một ứng dụng khách REST bằng một ngôn ngữ khác.
Jimmy T.

1
Chính xác, api vẫn sẽ tồn tại, với định nghĩa tuyến đường của nó, không có gì ngăn cản việc tạo ứng dụng khách bằng ngôn ngữ khác, nhưng miễn là bạn sử dụng java có thể sử dụng giao diện
Leonardo Villela
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.