Въведение

Комуникацията между клиент и сървър е съществен аспект на съвременните уеб приложения. С набиращата популярност архитектура на микроуслугите необходимостта от опростена комуникация клиент-сървър никога не е била по-критична. Spring Boot, изключително популярна Java рамка, предлага набор от инструменти, за да направи това взаимодействие безпроблемно и ефективно. Сред тези инструменти анотацията @FeignClient се откроява със своята лекота на използване и мощни функции.

В тази публикация ще проучим как да използваме анотацията @FeignClient на Spring за комуникация клиент-сървър. Ще разбием основните функции, ще демонстрираме някои примери и ще подчертаем най-добрите практики, за да увеличим максимално полезността му.

Въведение в @FeignClient

В днешния свят на микроуслуги и облачни приложения комуникацията между различни услуги е по-скоро правило, отколкото изключение. Микроуслугите често трябва да взаимодействат помежду си, за да изпълнят бизнес логиката, да заявяват данни или да обработват транзакции. Процесът на разрешаване на тази комуникация обаче може да стане сложен и податлив на грешки, ако не се управлява правилно. Тук влиза в действие @FeignClient на Spring Cloud, предлагайки стабилно, рационализирано решение за комуникация между услугите.

Защо @FeignClient е важно?

Докато традиционните монолитни архитектури се състоят от тясно свързани приложения с една кодова база, микроуслугите са по същество обратното. Те са колекция от слабо свързани услуги, всяка от които отговаря за определена част от функционалността. Тези услуги трябва да комуникират ефективно, за да предоставят сплотено потребителско изживяване.

Когато микроуслуга иска да извика API на друга услуга, разработчиците често използват HTTP клиенти или REST шаблони, за да направят тези извиквания. Въпреки че това са функционални методи, те включват много шаблонен код, което прави кодовата база по-трудна за поддържане и разбиране.

Анотацията @FeignClient рационализира този процес, като абстрахира HTTP клиентския слой, позволявайки на разработчиците да се съсредоточат повече върху бизнес логиката и по-малко върху инфраструктурните проблеми.

Ключови предимства

Декларативен подход

Най-убедителното предимство на използването на @FeignClient е неговият декларативен характер. Вие дефинирате интерфейс и го анотирате с @FeignClient, а Spring се грижи за останалото. Не е необходимо да пишете код за HTTP повиквания, настройки за връзка или анализ на отговор; Spring Boot се справя с всички тези проблеми зад кулисите.

Вградено балансиране на натоварването

Микроуслугите често се изпълняват в разпределена среда, където могат да съществуват множество екземпляри на услуга. Анотацията @FeignClient, когато се използва във връзка с Spring Cloud и регистър на услуги като Eureka, предлага вградено балансиране на натоварването от страна на клиента. Това означава, че заявките се насочват автоматично към различни екземпляри на услуги, осигурявайки както излишък, така и ефективно използване на ресурсите.

Интегрирана сигурност

@FeignClient също се интегрира добре с Spring Security, което ви позволява лесно да защитите комуникацията между услугите. Това гарантира, че услугите са удостоверени и оторизирани, преди да могат да комуникират помежду си.

Резервни механизми

В среда на микросервизи грешките в услугата не са необичайни. За да изградите устойчива система, можете да дефинирате резервни методи, които се задействат, когато услугата е недостъпна. Това допринася за устойчивостта на грешки на вашето приложение.

Как работи?

Анотацията @FeignClient работи чрез динамично създаване на прокси на анотирания интерфейс по време на изпълнение. Всеки метод в този интерфейс съответства на HTTP заявка към услугата, посочена в анотацията. Когато се извика метод на интерфейса, Spring прихваща това извикване и го превежда в HTTP заявка, включително съпоставяне на URL адреси, преобразуване на тялото на заявката и отговора и настройка на заглавката. След това изпраща тази заявка до целевата услуга, обработва отговора и го връща обратно като върната стойност на метода.

Интеграция с Spring Cloud

@FeignClient е неразделна част от екосистемата Spring Cloud, която е набор от инструменти за изграждане на облачни приложения. Когато се използва в проект на Spring Cloud, клиентът Feign получава допълнителни възможности като централизирана конфигурация и лесна интеграция с други модули на Spring Cloud, като Spring Cloud Stream или Spring Cloud Config.

Настройка на средата

За да се възползвате от @FeignClient на Spring, първо трябва да настроите правилно вашата среда за разработка. Този раздел очертава подход стъпка по стъпка, за да започнете с приложение Spring Boot и как да включите клиента Feign.

Създаване на нов пролетен стартиращ проект

Първото нещо, от което се нуждаете, е приложение Spring Boot. Ако започвате от нулата, можете лесно да генерирате скелет на проект с помощта на Spring Initializr:

  1. Отворете Spring Initializr.
  2. Изберете предпочитания от вас език (Java, Kotlin, Groovy).
  3. Изберете версията на Spring Boot (обикновено е добре да използвате най-новата стабилна версия).
  4. Добавете необходимите зависимости; на този етап можете да изберете „Spring Web“ и „Spring Cloud OpenFeign“.
  5. Щракнете върху „Генериране“, за да изтеглите ZIP файл, съдържащ проекта.

Добавяне на зависимости на Maven

След като вашият Spring Boot проект бъде генериран, отворете вашия pom.xml файл, за да добавите зависимости. Ако сте използвали Spring Initializr с правилните опции, може вече да имате тези зависимости във вашия pom.xml:

<dependencies>
  <!-- Spring Cloud Starter Feign -->
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
  </dependency>
  <!-- other dependencies -->
</dependencies>

Ако не сте използвали Spring Initializr, добавете тези зависимости ръчно.

Съвместимост на версията

Версиите на Spring Cloud са тясно свързани с версиите на Spring Boot. Когато добавяте зависимости, уверете се, че версията на Spring Cloud, която използвате, е съвместима с вашата версия на Spring Boot. Можете да проверите бележките по изданието на Spring Cloud за информация за съвместимост.

Активиране на Feign клиенти

След като зависимостите са налице, е време да активирате клиентите на Feign във вашето приложение Spring Boot. Това се прави с помощта на анотацията @EnableFeignClients. Добавете тази анотация към вашия основен клас на приложение Spring Boot, както следва:

@SpringBootApplication
@EnableFeignClients
public class MyApplication {
  public static void main(String[] args) {
    SpringApplication.run(MyApplication.class, args);
  }
}

Добавяйки @EnableFeignClients, вие казвате на Spring да сканира за интерфейси, които са анотирани с @FeignClient и да генерира прокси реализации за тях.

Алтернативни методи за добавяне на зависимости

Освен използването на Maven, можете също да използвате Gradle за управление на зависимостите. Процесът е до голяма степен същият; просто ще редактирате своя build.gradle файл вместо pom.xml. Ето как бихте добавили зависимостта на клиента Feign в Gradle:

dependencies {
  implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
  // other dependencies
}

Основна употреба на @FeignClient

Feign е по същество начин за писане на опростени HTTP клиенти. Основната идея зад неговата работа е да се напише интерфейс и да се анотират. След това Spring запълва празнините, като предоставя имплементация по време на изпълнение. По-долу ще преминем през стъпките за дефиниране и използване на Feign клиент за взаимодействие с друга услуга.

Създаване на Feign клиентски интерфейс

Крайъгълният камък на използването на @FeignClient е дефинирането на интерфейс, който служи като Feign клиент. Този интерфейс трябва да бъде анотиран с @FeignClient и да съдържа сигнатури на метод за операциите, които искате да извършите. Анотацията @FeignClient изисква поне един параметър: името на услугата, към която се свързвате.

Разгледайте следния пример, където дефинираме клиентски интерфейс на Feign за взаимодействие с хипотетичен Order-Service:

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.List;

@FeignClient("Order-Service")
public interface OrderClient {
  @GetMapping("/orders/{userId}")
  List<Order> getOrdersByUserId(@PathVariable("userId") String userId);
}

В този интерфейс сме дефинирали един метод getOrdersByUserId, който съответства на извличане на поръчки за даден потребителски идентификатор от Order-Service.

Анотации и техните роли

  1. @FeignClient(“Order-Service”): Тази анотация казва на Spring да създаде Feign клиент, който насочва заявките към микроуслугата Order-Service.
  2. @GetMapping(“/orders/{userId}”): Анотацията @GetMapping съпоставя метода HTTP GET с шаблона /orders/{userId} URL, който ще се използва за извличане на поръчките.
  3. @PathVariable(“userId”): Тази анотация обвързва променливата на пътя userId в URL адреса с параметъра на метода userId.

Инжектиране на Feign Client

След като интерфейсът е дефиниран, можете да го инжектирате във всеки компонент на Spring (като контролер или услуга), като използвате анотацията @Autowired на Spring.

Ето пример за Spring REST контролер, който използва интерфейса OrderClient за извличане на поръчки за даден потребител:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class UserController {
  @Autowired
  private OrderClient orderClient;

  @GetMapping("/user/{id}/orders")
  public List<Order> getUserOrders(@PathVariable("id") String id) {
    return orderClient.getOrdersByUserId(id);
  }
}

В този пример класът UserController има поле OrderClient, което автоматично се попълва от Spring. Методът getUserOrders просто делегира извикването на метода OrderClient.getOrdersByUserId, който под капака изпълнява HTTP заявката за извличане на данните.

Стартиране на приложението

След като сте дефинирали своя клиентски интерфейс Feign и сте го инжектирали в Spring компонент, стартирането на вашето Spring Boot приложение трябва да активира тази функция. Веднага след като приложението се изпълнява, всяко извикване на getUserOrders API ще използва вътрешно клиента Feign за извличане на данни от Order-Service.

Разширени функции и най-добри практики

Въпреки че @FeignClient опростява начина, по който микроуслугите комуникират, той също така предоставя изобилие от разширени функции и опции за персонализиране. Разбирането на тези функции може да помогне на разработчиците да изградят по-стабилни, гъвкави и оптимизирани приложения.

Персонализиране на параметрите на заявката

По подразбиране @FeignClient използва прости имена на параметри на метода като параметри на заявката. Това обаче може да се персонализира с помощта на анотацията @RequestParam.

@FeignClient("Order-Service")
public interface CustomOrderClient {
  @GetMapping("/orders")
  List<Order> getOrdersByStatus(@RequestParam("status") String orderStatus);
}

В този пример методът getOrdersByStatus ще извика крайната точка /orders на Order-Service и ще предаде status като параметър на заявката.

Балансиране на натоварването от страна на клиента с лента

Клиентите Feign могат лесно да бъдат интегрирани с лентата за балансиране на натоварването от страна на клиента. Всичко, което трябва да направите, е да включите зависимостта на лентата във вашия проект.

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

След като лентата е в класовата пътека, @FeignClient ще я използва, за да разпределя заявки между налични екземпляри на услуга, регистрирани в услуга за откриване като Eureka.

Справяне с повреди с Hystrix

Hystrix може да бъде интегриран за устойчивост на грешки. Може да се посочи резервен метод за обработка на случаи, когато целевата услуга не е налична.

Първо добавете зависимостта Hystrix към вашия pom.xml:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

След това посочете резервния клас във вашата @FeignClient дефиниция:

@FeignClient(name = "Order-Service", fallback = OrderClientFallback.class)
public interface OrderClient {
  // ...
}

@Component
public class OrderClientFallback implements OrderClient {
  @Override
  public List<Order> getOrdersByUserId(String userId) {
    return Collections.emptyList();
  }
}

Най-добри практики

  1. Конвенция за последователно именуване: Използвайте последователна конвенция за именуване за вашите клиентски интерфейси Feign. Това улеснява тяхното локализиране и управление.
  2. Отделен конфигурационен клас: За сложни клиенти използвайте отделен конфигурационен клас, където можете да дефинирате прехващачи на заявки, енкодери и декодери.
  3. Регистриране и наблюдение: Внедрете регистриране и наблюдение, за да проследите заявките, направени от Feign клиенти. Това може да ви помогне да отстраните грешки и да оптимизирате производителността на вашето приложение.
  4. Документация на крайната точка: Анотирайте своите Feign клиентски интерфейси с JavaDocs или коментари, особено когато API има сложни параметри на заявка, заглавки или тела на заявка/отговор.
  5. Изчакване и повторен опит: Винаги конфигурирайте изчакване и повторни опити, за да направите приложението си по-устойчиво. Можете да направите това или глобално, или на ниво клиент.

Заключение

В съвременните архитектури на микроуслуги комуникацията клиент-сървър е неразделна част от системата. Анотацията @FeignClient на рамката Spring опростява тази комуникация, като улеснява четенето, писането и поддържането на вашия код. С разширени функции като персонализиране на параметри, резервни механизми и вградено балансиране на натоварването от страна на клиента, Feign е мощен инструмент, който може да ви помогне да изградите стабилни и мащабируеми приложения.

Така че следващия път, когато се занимавате с комуникация клиент-сървър в приложение за Spring Boot, помислете дали да не използвате @FeignClient, за да направите живота си много по-лесен.

  1. Официална документация на Spring Cloud
  2. Страница на лентата на Netflix в GitHub
  3. Страница на GitHub на Netflix