In the previous article, I talked about service registration and discovery. In the microservice architecture, the business will be split into an independent service, and the communication between the service and the service is based on http restful. Spring cloud has two service invocation methods, one is ribbon+restTemplate, and the other is feign. In this article, first explain the ribbon+rest based.
I. Introduction to ribbon
Ribbon is a load balancing client, which can well control some behaviors of htt and tcp. Feign integrates ribbon by default.
ribbon has implemented these configuration beans by default:
IClientConfig ribbonClientConfig: DefaultClientConfigImpl
IRule ribbonRule: ZoneAvoidanceRule
IPing ribbonPing: NoOpPing< /p>
ServerList ribbonServerList: ConfigurationBasedServerList
ServerListFilter ribbonServerListFilter: ZonePreferenceServerListFilter
ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer
Second, preparations
this article Based on the project in the previous article, start the eureka-server project; start the service-hi project, its port is 8762; change the port of the service-hi configuration file to 8763, and start it, then you will find: service- hi has registered 2 instances on eureka-server, which is equivalent to a small cluster.
Visit localhost:8761 as shown in the figure: there are two clients.
3. Build a service consumer
Create a new spring-boot project and name it: service-ribbon;
in its pom .xml inherits the parent pom file and introduces the following dependencies:
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.liu
SpringCloudLearn01
1.0-SNAPSHOT
com.liu.example
service-ribbon
0.0.1-SNAPSHOT
service-ribbon
Demo project for Spring Boot
1.8
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
In the configuration file of the project, specify the service registration center address as http://localhost:8761/eureka/, the program name is service-ribbon, and the program The port is 8764. The configuration file application.yml is as follows:
server:
port: 8764
spring:
application:
name: service-ribbon
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
In the startup class of the project, register with the service center through @EnableDiscoveryClient; and inject a bean: restTemplate into the program’s ioc; and use the @LoadBalanced annotation to indicate that this restRemplate opens load balancing Function.
package com.liu.example. serviceribbon;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
Write a test class HelloService, and consume the “/hi” interface of the service-hi service through the restTemplate injected into the ioc container. Here we directly The program name is used instead of the specific URL address. In ribbon, it will select the specific service instance according to the service name. According to the service instance, it will replace the service name with the specific URL when requesting. The code is as follows:
package com.liu.example.serviceribbon.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand ;
import com.netflix.ribbon.proxy.annotation.Hystrix;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
public String hiService(String name) {
return restTemplate.getForObject("http://service-client/hi", String.class);
}
}
Write a controller, use the method of calling HelloService in the controller, the code is as follows:
package com.liu.example.serviceribbon.controller;
import com.liu.example.serviceribbon.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Autowired
HelloService helloService;
@GetMapping(value = "/hi")
public String hi(@RequestParam String name) {
return helloService.hiService( name );
}
}
Visit http://localhost:8764/hi?name=forezp multiple times on the browser, the browser alternately displays:
hello! My port number is: 8762
hello! My port number is: 8763
This shows that when we call restTemplate.getForObject(“http:// In the SERVICE-HI/hi?name=”+name,String.class) method, load balancing has been done and service instances of different ports have been accessed.
Four. Architecture at this time
A service registry, eureka server, port 8761
The service-hi project ran two instances, the ports are 8762,8763 respectively , Respectively register with the service registry
sercvice-ribbon port is 8764, and register with the service registry
When sercvice-ribbon calls the hi interface of service-hi through restTemplate, because the ribbon is used for load balancing, it will take turns Call service-hi: hi interface of two ports 8762 and 8763;
Source code download: https://github.com/MrLiu1227/MySpringCloud.git
< ?xml version="1.0" encoding="UTF-8"?>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.liu
SpringCloudLearn01
1.0-SNAPSHOT
com.liu.example
service-ribbon
0.0.1-SNAPSHOT
service-ribbon
Demo project for Spring Boot
1.8
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
server:
port: 8764
spring:
application:
name: service-ribbon
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
package com.liu.example .serviceribbon;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
package com.liu.example.serviceribbon.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand ;
import com.netflix.ribbon.proxy.annotation.Hystrix;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
public String hiService(String name) {
return restTemplate.getForObject("http://service-client/hi", String.class);
}
}
package com.liu.example.serviceribbon.controller;
import com.liu.example.serviceribbon.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Autowired
HelloService helloService;
@GetMapping(value = "/hi")
public String hi(@RequestParam String name) {
return helloService.hiService( name );
}
}