В предыдущей статье я рассказывал о регистрации и учете сервисов. В микросервисной архитектуре отдел обнаружения обслуживается самостоятельно, а связь между сервисами и службами основана на http restful. В Spring cloud есть методы вызова бизнес-сервисов, один из них — ribbon+template, другой — ribbon+rest.
1. Введение в ribbon
Ribbon — это клиент для балансировки нагрузки, который может хорошо контролировать некоторые поведения http и tcp. Feign интегрирует ribbon по умолчанию.
ribbon уже реализует эти конфигурационные бобы по умолчанию:
-
IClientConfig ribbonClientConfig: DefaultClientConfigImpl
-
IRule ribbonRule: ZoneAvoidanceRule
-
IPing ribbonPing: NoOpPing
-
ServerList ribbonServerList: ConfigurationBasedServerList
-
ServerListFilter ribbonServerListFilter: ZonePreferenceServerListFilter
-
ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer
2.Подготовка
Эта статья основана на проекте предыдущей статьи, запустите проект eureka-server; запустите проект service-hi, его порт 8762; измените порт конфигурационного файла service-hi на 8763 и запустите его, после чего вы обнаружите: service-hi зарегистрировал 2 экземпляра в eureka-server, что эквивалентно небольшому кластеру.
3. Построение потребителя услуг
Создайте новый проект spring-boot и назовите его: service-ribbon;
В своем pom.xml он наследует родительский pom-файл и вводит следующие зависимости:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.forezp</groupId>
<artifactId>service-ribbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>service-ribbon</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.forezp</groupId>
<artifactId>sc-f-chapter2</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
</project>
В конфигурационном файле проекта адрес реестра указанной службы — http://localhost:8761/eureka/, имя программы — service-ribbon, порт программы — 8764. Конфигурационный файл application.yml имеет следующий вид:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8764
spring:
application:
name: service-ribbon
В стартовом классе проекта зарегистрируйтесь в сервисном центре через @EnableDiscoveryClient; внедрите боб: restTemplate в ioc программы; используйте аннотацию @LoadBalanced, чтобы указать, что этот restRemplate включает балансировку нагрузки.
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run( ServiceRibbonApplication.class, args );
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
Напишите тестовый класс HelloService и используйте интерфейс «/hi» сервиса service-hi через restTemplate, внедренный в контейнер ioc. Здесь мы напрямую заменяем конкретный url-адрес на название программы. В ленте оно будет основано на имени сервиса. Выберите конкретный экземпляр сервиса и замените имя сервиса на конкретный url при запросе в соответствии с экземпляром сервиса. Код выглядит следующим образом:
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
public String hiService(String name) {
return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);
}
}
Напишите контроллер и используйте метод вызова HelloService в контроллере. Код выглядит следующим образом
@RestController
public class HelloControler {
@Autowired
HelloService helloService;
@GetMapping(value = "/hi")
public String hi(@RequestParam String name) {
return helloService.hiService( name );
}
}
Зайдите на сайт http://localhost:8764/hi?name=forezp несколько раз в браузере, и браузер попеременно отображает:
hi forezp,i am from port:8762
hi forezp,i am from port:8763
Это показывает, что при вызове метода restTemplate.getForObject(«http://SERVICE-HI/hi?name=»+name,String.class) мы выполнили балансировку нагрузки и получили доступ к экземплярам сервиса на разных портах.
4. структура на данный момент
Реестр сервисов, сервер eureka, порт 8761.
Проект service-hi запустил два экземпляра с портами 8762 и 8763, которые были зарегистрированы в реестре сервисов соответственно.
Порт sercvice-ribbon — 8764, зарегистрированный в реестре сервисов.
Когда sercvice-ribbon вызывает hi интерфейс service-hi через restTemplate, из-за балансировки нагрузки с ribbon, он будет поочередно вызывать hi интерфейс service-hi: порты 8762 и 8763;