您的位置:首页 > 编程语言 > Java开发

Spring Cloud+Eureka+Ribbon实现客户端负载均衡

2017-08-29 09:33 1246 查看

Spring Cloud+Eureka+Ribbon实现客户端负载均衡

最近在学习springcloud,自己总结的客户端负载均衡,拿出来分享下

eureka高可用注册中心

服务提供者

服务发现及消费

负载均衡

搭建eureka高可用注册中心

pom文件,引入spring-cloud-starter-eureka-server 注册中心的核心依赖;最后的Build标签是需要打包成jar包需要的依赖。

<?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.eurekaDemo</groupId>
<artifactId>eurekaDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>eurekaDemo</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.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.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</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.SR1</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>
</project>


创建启动类EurekaDemoSpring类,其中EnableEurekaServer注解表明其为注册中心

@EnableEurekaServer //表示注册中心
@SpringBootApplication
public class EurekaDemoApplication {

public static void main(String[] args) {
SpringApplication.run(EurekaDemoApplication.class, args);
}


新建application.peer1.properties配置文件,作为peer1的服务中心配置,并将serverUrl指向peer2,其中register-with-eureka=true注册中心可以注册自己

spring.application.name=eureka-server1
server.port=1111

eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.instance.hostname=peer1
eureka.client.serviceUrl.defaultZone=http://peer2:1112/eureka/


同理,新建peer2注册中心

spring.application.name=eureka-server2
server.port=1112

eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.instance.hostname=peer2
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/


这样,即可形成一对互相注册的高可用注册中心, 在访问之前我们需要修改下hosts文件,添加

127.0.0.1 peer1
127.0.0.1 peer2


maven打包程序 mvn install,之后找到jar包位置,以java -xxx.jar方式分别启动peer1与peer2

java -xxx.jar --spring.profiles.active=peer1
java -xxx.jar --spring.profiles.active=peer2


此时访问localhost:1111即可看到注册的服务

编写服务提供者

注册中心搭建完成后,我们继续搭建服务提供者,编写pom文件,引入注册服务提供者核心依赖spring-cloud-starter-eureka

<?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.springboot</groupId>
<artifactId>springbootDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>springbootDemo</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.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.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-eureka</artifactId>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.SR5</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>
</project>


编写主类文件

@EnableDiscoveryClient //激活Eureka中DiscoveryClient实现,通过其可获取服务信息
@SpringBootApplication
public class SpringbootDemoApplication {

public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class,args);
}
}


新建一个控制类,其中DiscoveryClient可以获取注册中心注册的服务

@RestController
public class HelloController {

private final Logger logger = Logger.getLogger(getClass());

@Autowired
private DiscoveryClient discoveryClient;

@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String index(){
ServiceInstance instance = discoveryClient.getLocalServiceInstance();
logger.info("++++++++++++++++++++++++++++"+instance.getServiceId());
return "Hello";
}
}


编写application.properties将服务注册到注册中心

spring.application.name=hello-service
eureka.client.service-url.defaultZone=http://peer1:1111/eureka,http://peer2:1112/eureka


同样我们将其打成jar包,分别以8081及8082端口启动两个服务提供者,为后续的服务消费负载均衡做准备

java -jar xxx.jar --serveer.port=8081
java -jar xxx.jar --serveer.port=8082


启动后刷新localhost:1111可看到有四个服务,如下图



这样服务提供者也编写完成,下面我们完成服务发现及消费

服务发现与消费

服务发现由Eureka实现,服务消费由Ribbon实现,我们新建一个基础的springboot项目,起名为ribbon-consumer;

编写pom文件,引入Ribbon依赖spring-cloud-starter-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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>

<groupId>com.ribbon.consumer</groupId>
<artifactId>ribbon-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>ribbon-consumer</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.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.boot</groupId>
<artifactId>spring-boot-starter</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-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-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</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>
</project>


新建应用主类RibbonConsumerApplication,其中@EnableDiscoveryClient注解表示其为客户端应用,并且需要开启客户端负载均衡@LoadBalanced

@EnableDiscoveryClient //eureka客户端应用
@SpringBootApplication
public class RibbonConsumerApplication {

@Bean
@LoadBalanced  //开启客户端负载均衡
RestTemplate restTemplate(){
return new RestTemplate();
}

public static void main(String[] args) {
SpringApplication.run(RibbonConsumerApplication.class, args);
}
}


新建controller类,可以看到服务地址是服务名加访问路径,这在服务治理框架中是一个非常重要的特性;

@RestController
public class ConsumerController {

@Autowired
RestTemplate restTemplate;

@RequestMapping(value = "/helloConsumer",method = RequestMethod.GET)
public String helloConsumer(){
return restTemplate.getForEntity("http://HELLO-SERVICE/hello",String.class).getBody();
}
}


编写application配置文件

spring.application.name=ribbon-consumer
server.port=9000

eureka.client.service-url.defaultZone=http://localhost:1111/eureka/


启动此应用,我们在eureka面板可以看到我们的ribbon服务



通过访问http://localhost:9000/helloConsumer 成功返回Hello,此时可以看到控制台输出了所有服务的实例信息、第一次连接信息、上次连接信息等重要数据,尝试发送多次请求,可以看到8081与8082服务轮流输出日志,以此可以判断ribbon帮我们实现了客户端负载均衡



负载均衡机制

上面实现了最简单的负载均衡,负载均衡有很多负载机制

1. RandomRule:随机轮询策略,查询所有的服务列表allList与可用实例列表upLIst,根据 random.netInt(allLIst.size())作为参数i,来upList[i]的服务实例,可能会出现死循环导致BUG

2. RoundRobinRule:线性轮询策略。通过调用递增函数查找服务例;循环查询次数超过10次,则停止查询,并返回警告

3. RetryRule:重试机制的实例选择。实现在deadline时间内,不断尝试去查询实例,若时间段内未找到实例, 则返回null;

4. WeightedResponseTimeRule:权重策略。是RoundRobinRule扩展,会根据实例运行情况来计算权重,以此来挑选权重,包括是三个核心内容

5. BestAvailableRule:最闲策略;他通过遍历均衡器所有实例,过滤掉故障实例,找出并发请求数目最小的一个,即找到最闲的实例

6. PredicateBasedRule:抽象策略。首先过滤一些服务实例,然后再以线性轮询的方式选出一个实例
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: