First, the role of service in the micro-Ribbon
1. What is the Ribbon
1.Ribbon is based on HTTP and TCP client load balancing tool , which is based implementation Netflix Ribbon
2. It is not like Spring Cloud service registration center, distribution center, API gateway as stand-alone deployment, but it exists in almost every Spring Cloud micro service. Declarative service call Feign is provided based implementation Ribbon.
3.Ribbon offers a variety of load balancing algorithms, for example: polling, random, and so on. Even includes a custom load balancing algorithm.
2.Ribbon solve the problem
It addresses and provides a micro-service load balancing problem
Second, within a centralized process and load balancing difference
1. Classification load balancing solution
The industry mainstream load balancing scheme can be divided into two categories:
-
Centralized Load balancing: the use of a separate load balancing facility in consumer and intermediate provider (either hardware, such as F5, can be software, such as: Nginx), access to the facility by the request is forwarded to the provider through a strategy
-
In-process load balancing: The load balancing logic integrated into consumer, consumer service registry learn from what address is available, then myself and then select an appropriate provider from these addresses
Ribbon latter, it is just a class library, integrated in the consumer, consumer to obtain an appropriate provider address it.
2. State Chart load balancing methods
Three, Ribbon entry case
Ribbon strategy for load balancing cluster service uses the default polling
1.Consumer
@Service
public class UserService {
@Autowired
private LoadBalancerClient loadBalancerClient; //ribbon:负载均衡器
public List<User> getUsers(){
//选择调用的服务的名称
//ServiceInstance:封装了服务的基本信息,如:ip、端口号
ServiceInstance si = loadBalancerClient.choose("eureka-provider");
//拼接访问服务的url
StringBuffer sb = new StringBuffer();
//http://localhost:9090/user
sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/user");
System.out.println(sb.toString());
//SpringMVC RestTemplate
RestTemplate restTemplate = new RestTemplate();
ParameterizedTypeReference<List<User>> type = new ParameterizedTypeReference<List<User>>() {
};
//ResponseEntity:封装了返回值信息
ResponseEntity<List<User>> entity = restTemplate.exchange(sb.toString(), HttpMethod.GET, null, type);
return entity.getBody();
}
}
复制代码
2.Consumer profile
spring.application.name=eureka-consumer
server.port=9091
#设置服务注册中心地址,向所有注册中心做注册
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
复制代码
3.Provider cluster deployment
3.1 The Provider packaged, deployed to linux environment
3.2 Creating a Startup Script
#!/bin/bash
cd `dirname $0`
CUR_SHELL_DIR=`pwd`
CUR_SHELL_NAME=`basename ${BASH_SOURCE}`
JAR_NAME="springcloud-eureka-provider-0.0.1-SNAPSHOT.jar"
JAR_PATH=$CUR_SHELL_DIR/$JAR_NAME
#JAVA_MEM_OPTS=" -server -Xms1024m -Xmx1024m -XX:PermSize=128m"
JAVA_MEM_OPTS=""
#SPRING_PROFILES_ACTIV="-Dspring.profiles.active=eureka2"
SPRING_PROFILES_ACTIV=""
LOG_DIR=$CUR_SHELL_DIR/logs
LOG_PATH=$LOG_DIR/${JAR_NAME%..log
echo_help()
{
echo -e "syntax: sh $CUR_SHELL_NAME start|stop"
}
if [ -z $1 ];then
echo_help
exit 1
fi
if [ ! -d "$LOG_DIR" ];then
mkdir "$LOG_DIR"
fi
if [ ! -f "$LOG_PATH" ];then
touch "$LOG_DIR"
fi
if [ "$1" == "start" ];then
# check server
PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
if [ -n "$PIDS" ]; then
echo -e "ERROR: The $JAR_NAME already started and the PID is ${PIDS}."
exit 1
fi
echo "Starting the $JAR_NAME..."
# start
nohup java $JAVA_MEM_OPTS -jar $SPRING_PROFILES_ACTIV $JAR_PATH >> $LOG_PATH 2>&1 &
COUNT=0
while [ $COUNT -lt 1 ]; do
sleep 1
COUNT=`ps --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}' | wc -l`
if [ $COUNT -gt 0 ]; then
break
fi
done
PIDS=`ps --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}'`
echo "${JAR_NAME} Started and the PID is ${PIDS}."
echo "You can check the log file in ${LOG_PATH} for details."
elif [ "$1" == "stop" ];then
PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
if [ -z "$PIDS" ]; then
echo "ERROR:The $JAR_NAME does not started!"
exit 1
fi
echo -e "Stopping the $JAR_NAME..."
for PID in $PIDS; do
kill $PID > /dev/null 2>&1
done
COUNT=0
while [ $COUNT -lt 1 ]; do
sleep 1
COUNT=1
for PID in $PIDS ; do
PID_EXIST=`ps --no-heading -p $PID`
if [ -n "$PID_EXIST" ]; then
COUNT=0
break
fi
done
done
echo -e "${JAR_NAME} Stopped and the PID is ${PIDS}."
else
echo_help
exit 1
fi
复制代码
4. Start consumer
Four, Ribbon common load balancing strategy
1. Polling Policy (default):
The use of RoundRobinRule
classes, each time the polling policy sequence indicates a Provider removed, such as Provider 5 has, for the first time to take the first, the second to take a second, a third take the third, and so on .
2. Weight polling policies:
The use of WeightedResponseTimeRule
classes, according to each Provider's response time assigned a weight, the weight increase response time smaller, less likely to be selected.
Principle: a start polling policy, and start a timer, collected once every 30s on average each provider's response time , when the information is sufficient to add a weight for each provider, and press weights randomly selected, the higher the weight is the higher the probability selected.
3. random strategy:
Use RandomRule
class provider from the list of randomly selecting a provider
4. The minimum number of concurrent strategies:
Use BestAvailableRule
, select the request is a small number of concurrent of provider, unless the provider in the fuse.
5. retry mechanism in selected "load balancing policy" on the basis of
Use RetryRule
class, "the selected load balancing strategy" The strategy is polling policy RoundRobinRule
The retry strategy to set a threshold period of time , if the selected provider is not successful in this period of time, has been trying to adopt the "Selected load balancing strategy: Polling Policy" last select an available provider
6. Availability sensitive policy
The use of AvailabilityFilteringRule
classes, poor filtration performance provider There are two:
The first: Eureka has been filtered out connection fails provider of
The second: to filter out high concurrency provider of
7. Regional Strategy sensitivity
Use ZoneAvoidanceRule
class,
To examine the availability of a regional basis, to discard the whole area is not available, from the remaining region of the selected provider is available
If there is within the area of one or more instances ip unreachable or slow response, both decreases within the region other ip ip selected weights .
Five, Ribbon specify a different load balancing strategy
1. Modify the code to replace the load balancing strategy
1.1 Creating project
springcloud-eureka-consumer-LB
1.2 Add method to create a load balancing policy object in the startup class
/**
* Author: LuYi
* Date: 2019/11/5 17:32
* Description: 描述
*/
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
@Bean
public RandomRule createRule() {
return new RandomRule();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
复制代码
2. Modify the configuration file to replace the load balancing policy
#设置负载均衡策略 eureka-provider 为调用的服务的名称
eureka-provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
复制代码
Six, Ribbon peer Direct Connect
1. Create a project
springcloud-eureka-consumer-direct
2. Remove the Eureka coordinates, the coordinates added Ribbon
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.13.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.luyi</groupId>
<artifactId>springcloud-eureka-consumer-direct</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-eureka-consumer-direct</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--ribbon坐标-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
复制代码
3. Modify the configuration file to remove the related Eureka configuration, add a new configuration item
spring.application.name=eureka-consumer-direct
server.port=9091
#禁用 eureka
ribbon.eureka.enabled=false
#指定具体的服务实例清单
eureka-provider.ribbon.listOfServers=192.168.234.132:9090
复制代码
4. Modify the startup class, an error code is removed
@SpringBootApplication
public class ConsumerApplication {
// @Bean
// public RandomRule createRule() {
// return new RandomRule();
// }
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
复制代码