Preface: Microservice architecture inevitably has multiple instances of a single microservice. So how can the client allocate requests to instances of multiple microservices? Here we need to use load balancing
1. Introduction to Ribbon
Ribbon is a load balancer released by Netflix, which helps control the behavior of HTTP and TCP clients. After configuring the service provider address list for Ribbon, Ribbon can automatically help service consumers to request based on some load balancing algorithm. Ribbon provides us with a lot of load balancing algorithms by default, such as polling, randomness, etc., which can also be customized;
Ribbon's GitHub: https://github.com/Netflix/ribbon
When using Ribbon and Eureka in SpringCloud, Ribbon will automatically obtain the list of service provider addresses from EurekaServer and based on the load balancing algorithm.
2. Ribbon actual combat
1. Create EurekaServer, EurekaClient1, EurekaClient2. I have mentioned the use of Eureka before, so here is the code:
EurekaServer:
ServerApplication.java
@SpringBootApplication@EnableEurekaServerpublic class ServerApplication { public static void main(String[] args) { SpringApplication.run(ServerApplication.class,args); }}pom.xml
<?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.cn</groupId> <artifactId>eureka-ribbon-server</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.13.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.</groupId> <artifactId></artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependency> </dependency> </dependency> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependency> </dependencyManagement> <!-- Add spring-boot maven plugin--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
application.properties
server.port=8761#Note: These two configurations are true by default. You must change to false, otherwise an error will be reported. Connot connect server# indicates whether to register itself on EurekaServer eureka.client.register-with-eureka=false# indicates whether to obtain registration information from EurekaServer eureka.client.fetch-registry=falseeureka.client.service-url.defaultZone=http://localhost:8761/eureka/
EurekaClient1:
pom.xml
<?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.cn</groupId> <artifactId>eureka-ribbon-client</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.13.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> </dependency> </dependency> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependency> </dependencyManagement> <!-- Add spring-boot maven plugin--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
server.port=8762spring.application.name=client-8762eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
Add RestTemplate remote call instance to the container in the startup class and add LoadBalanced annotation to make RestTemplate have the ability to load balancing:
@SpringBootApplication@EnableDiscoveryClientpublic class ClientApplication { public static void main(String[] args) { SpringApplication.run(ClientApplication.class, args); } /** * @Description: Adding the @LoadBalanced annotation to add load balancing capabilities to RestTemplate* @Param: * @return: * @Author: * @Date: 2018/6/15 */ @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); }}Create a Controller, inject RestTemplate and LoadBalancerClient instances:
package com.cn.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.client.RestTemplate;/** * @program: springcloud-example * @description: * @author: * @create: 2018-06-15 15:55 **/@Controllerpublic class RibbonController { @Autowired private LoadBalancerClient loadBalancerClient; @Autowired private RestTemplate restTemplate; @GetMapping("/loadInstance") @ResponseBody public String loadInstance() { ServiceInstance choose = this.loadBalancerClient.choose("client-87"); System.out.println(choose.getServiceId()+":"+choose.getHost()+":"+choose.getPort()); return choose.getServiceId() + ":" + choose.getHost() + ":" + choose.getPort(); }} package com.cn;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;/** * @program: springcloud-example * @description: * @author: 535504 * @create: 2018-06-15 16:05 **/@SpringBootApplication@EnableDiscoveryClientpublic class ClientApplication { public static void main(String[] args) { SpringApplication.run(ClientApplication.class, args); }}EurekaClient2:
pom.xml is consistent with EurekaClient1
application.xml:
server.port=8763spring.application.name=client-87eureka.client.service-url.defaultZone=http://localhost:8761/eureka
ClientController.java:
package com.cn.contorller;import org.springframework.steretype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.ResponseBody;/** * @program: springcloud-example * @description: * @author: * @create: 2018-06-15 16:12 **/@Controllerpublic class ClientController { @GetMapping("/getUser") @ResponseBody public String getUser() { System.out.println("Get user successful"); return "Get user successful"; }}2. Startup sequence:
①. Start EurekaServer =》 EurekaClient1 =》 EurekaClient2;
②. Then change server.port=8763 of application.properties in EurekaClient2 to server.port=8764, and start the project again;
③. Open the EurekaServer configuration page (http://localhost:8761/), as follows:
④. We enter http://localhost:8762/loadInstance in the address bar and refresh it a few times. You will find that the port instances are different each time we call it, as shown in the figure below:
⑤. We are looking at the console, as shown in the picture:
At this point, Ribbon has already started. Isn’t it very simple? But this is just the simplest application, and it’s a waste of time... There is no end to learning!
Sample code: https://gitee.com/lfalex/springcloud-example