SpringCloud Tutorial Part 2: Ribbon

Keywords: Programming Spring Maven Apache xml

In the previous article, we talked about registering and discovering services.In the microservice architecture, services are split into separate services, and the communication between services is based on http restful.Spring cloud has two ways of invoking services, ribbon+restTemplate and feign.This article starts with ribbon+rest.

1. Introduction to ribbon

Ribbon is a client side load balancer which gives you a lot of control over the behaviour of HTTP and TCP clients. Feign already uses Ribbon, so if you are using @FeignClient then this section also applies.

—–From the official website

Ribbon is a load balancing client that can control some htt and tcp behavior very well.Feign integrates ribbon by default.

ribbon has implemented these configuration bean s by default:

  • IClientConfig ribbonClientConfig: DefaultClientConfigImpl

  • IRule ribbonRule: ZoneAvoidanceRule

  • IPing ribbonPing: NoOpPing

  • ServerList ribbonServerList: ConfigurationBasedServerList

  • ServerListFilter ribbonServerListFilter: ZonePreferenceServerListFilter

  • ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer

2. Preparations

This article starts the eureka-server project based on the previous article's project; starts the service-hi project, with port 8762; changes the port of the service-hi configuration file to 8763, and starts. You will find that service-hi registers two instances in eureka-server, which is equivalent to a small cluster.Visit localhost:8761 as shown in the diagram:

3. Build a service consumer

Re-create a new spring-boot project named service-ribbon; in its pom.xml file, introduce the start-dependent spring-cloud-starter-eureka, spring-cloud-starter-ribbon, spring-boot-starter-web, respectively, with the following code:

<?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>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-ribbon</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Dalston.RC1</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>


</project>


The project configuration file specifies that the registry address of the service is http://localhost:8761/eureka/, the program name is service-ribbon, and the program port is 8764.The configuration file application.yml is as follows:

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8764
spring:
  application:
    name: service-ribbon

In the project's startup class, register with the service center through @EnableDiscoveryClient; and inject a bean: restTemplate into the program's ioc; and indicate by the @LoadBalanced annotation that this restRemplate turns on load balancing.

@SpringBootApplication
@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 that consumes the'/hi'interface of the service-hi service by previously injecting the restTemplate of the ioc container. Here we use the program name directly instead of the specific url address. In ribbon it will select a specific service instance based on the service name and use it when requestedThe url of the body replaces the service name with the following code:

@Service
public class HelloService {

    @Autowired
    RestTemplate restTemplate;

    public String hiService(String name) {
        return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);
    }

}

Write a controller in which to call HelloService using the following code:


/**
 * Created by fangzhipeng on 2017/4/6.
 */
@RestController
public class HelloControler {

    @Autowired
    HelloService helloService;
    @RequestMapping(value = "/hi")
    public String hi(@RequestParam String name){
        return helloService.hiService(name);
    }


}

Multiple visits to http://localhost:8764/hi?name=forezp on the browser, alternating browser display:

hi forezp,i am from port:8762

hi forezp,i am from port:8763

This means that when we invoke the restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class) method, we have done load balancing and accessed service instances on different ports.

4. Architecture at this time

  • A service registry, eureka server, port 8761
  • The service-hi project runs two instances, with ports 8762,8763, registering with the service registry
  • sercvice-ribbon port 8764, register with service registry
  • When sercvice-ribbon invokes the hi interface of service-hi through restTemplate, it invokes the hi interface of service-hi:8762 and 8763 ports in turn because of load balancing with ribbon;

Source download: https://github.com/forezp/SpringCloudLearning/tree/master/chapter2

5. References

This article refers to the following:

spring-cloud-ribbon

springcloud ribbon with eureka

Posted by @sh on Wed, 25 Sep 2019 18:56:46 -0700