Czytałem dokumentację Spring Cloud Netflix, gdy dowiedziałem się o sposobie udostępniania interfejsu między serwerem HTTP a jego klientem. Korzystają z tego przykładu w przypadku mikrousług, chociaż nie ma powodu, dla którego nie może ono obejmować ogólnej komunikacji HTTP:
// 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 {
}
Definiuje to interfejs, który jest używany zarówno jako serwer (Spring @RestController
zamienia go w serwer HTTP), jak i klient (Feign @FeignClient
konfiguruje go do użytku klienta HTTP). Implementacje klasy serwer i klient mogą być używane w oddzielnych projektach, ale nadal używają tego samego interfejsu, aby zapewnić zgodność typów.
Jednak pod tym przykładem podają następujące zastrzeżenie:
Uwaga: Zasadniczo nie zaleca się udostępniania interfejsu między serwerem a klientem. Wprowadza ścisłe sprzężenie, a także faktycznie nie działa z Spring MVC w obecnej formie (mapowanie parametrów metody nie jest dziedziczone).
OK, więc nie jest teraz dobrze zintegrowany ... ale ta część pojawia się po ostrzeżeniu przed udostępnianiem kodu i wprowadzeniem sprzężenia między serwerem a klientem, co według nich jest ważniejsze. Dlaczego uważają, że dzielenie interfejsu w ten sposób jest kiepskim pomysłem?
Bez tego tracisz możliwość zagwarantowania, że serwer i klient wysyłają sobie nawzajem dane, które mogą zrozumieć. Możesz dodać pole do jednego, ale nie do drugiego, i wykryć niezgodność tylko do czasu wykonania. Moim zdaniem nie wprowadza sprzężenia, ale jedynie ujawnia sprzężenie, które już istnieje. Czy potrzeba, aby serwery były całkowicie niezależne, jest większa niż potrzeba poinformowania ich, jakie typy danych otrzymają?
źródło
Odpowiedzi:
Powodem tego jest to, że powoduje ścisłe połączenie platformy klienta z platformą serwera. Oznacza to, że Twój klient musi używać języka / platformy, której używasz na serwerze, aby zrozumieć oczekiwaną umowę serwera. Należy zauważyć, że istnieje różnica między udostępnianiem tego samego kodu (artefaktu określonego języka / platformy) a uzgadnianiem konkretnej umowy.
Wiele projektów używa zamiast tego dokumentacji do swoich umów. Przykładowe żądania i odpowiedzi w neutralnym formacie (np. JSON) w stosunku do standardowych protokołów (np. REST). (Zobacz na przykład dokumenty API Stripe ). Ponieważ niepraktyczne jest pisanie umowy opartej na kodzie dla każdej możliwej platformy klienckiej, której możesz chcieć używać lub na którą zezwalasz. Jeszcze inni używają narzędzi do zarządzania API do definiowania neutralnych kontraktów .
Twój przykład dodania pola jest osobną kwestią - przykład, dlaczego ważne jest, aby wersja umów API była ważna. Pozwól klientom korzystać z wersji, dla której zostały zaprojektowane. Obok starej istnieje nowa, niekompatybilna wersja API. Klient starej wersji kontynuuje działanie, dopóki jego zespół nie zaktualizuje go lub nie wycofa starej wersji (po okresie wycofania / migracji). Zobacz Równoległa zmiana .
Postępowanie zgodnie z (domyślną poradą w) ostrzeżeniem pomaga klientowi i serwerowi ewoluować w sposób i dla każdego z nich. Jeśli możesz w uzasadniony sposób zagwarantować, że Twój serwer i klient zawsze będą współużytkować ten sam język / platformę ORAZ ewoluować w tym samym tempie, wówczas użycie artefaktu kodu specyficznego dla języka i platformy, ponieważ umowa prawdopodobnie będzie w porządku. Jednak prawdopodobnie nie jest to uzasadnione oczekiwanie, szczególnie w przypadku projektów ukierunkowanych na system Netflix OSS (coś specjalnie ukierunkowanego na skalowalność i wydajność chmury, przy całej tej wymaganej złożoności).
źródło