1. 简介
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.
- Ribbon 带有负载均衡功能
- Fegin实现基于Ribbon
2. 代码实现
2.1涉及的模块
- eureka-server-singleton:服务注册中心,端口8761
- eureka-service: 服务提供者,通过profile指定不同端口模拟一组微服务,端口8762、8763
- eureka-service-ribbon:通过Ribbon调用服务提供者提供的服务
2.2 源代码
2.2.1 Github地址
https://github.com/andyChenHuaYing/spring-cloud-demo
2.2.2 切换
暂时不再采用切换到commit版本,很多小的修正都是后面才修正的,前期没有规划好,导致切换之后牵连到一些环境问题需要配置,统一使用第一次发布的release版本 1.0.0,可通过tag切换git tag -d v1.0
,若想修改,可根据此tag创建新的分支。
2.3 eureka-server-singleton
与 二:Spring Cloud 之Eureka服务发布与注册没有任何区别。
2.4 eureka-service
基于 三:Spring Cloud 之Eureka服务发布与注册 改造,其他不变,修改application.yml,利用SpringBoot 的profile特性启动注册两个相同功能的服务实例。
2.4.1 application-8762.yml
两个配置文件端口不同,其他都一致。拆开放,结构更清晰
server:
port: 8762
spring:
application:
name: eureka-service
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
2.4.2 application-8763.yml
两个配置文件端口不同,其他都一致。
server:
port: 8763
spring:
application:
name: eureka-service
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
2.5 eureka-service-ribbon
2.5.1整体实现步骤
- pom.xml中引入
eureka-server
和netfix-ribbon
依赖 - application.yml中指定配置项,端口、application name、eureka-server地址
- SpringBoot 启动类添加注解
@EnableEurekaClient @EnableDiscoveryClient
- 使用
@Bean @LoadBalanced
向Spring容器注入org.springframework.web.client.RestTemplate
实例 - 在使用之处使用
@Autowired public RestTemplate restTemplate;
获取实例,调用服务提供方提供的方法
2.5.2 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">
<parent>
<artifactId>spring-cloud-finchley-demo</artifactId>
<groupId>org.oscar.scd</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-service-ribbon</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</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-netflix-ribbon</artifactId>
</dependency>
</dependencies>
</project>
2.5.2 application.yml
server:
port: 8764
spring:
application:
name: eureka-service-ribbon
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
2.5.3 EurekaServiceRibbonApplication
package org.oscar.scd.eureka.service.ribbon;
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.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableEurekaClient
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaServiceRibbonApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(EurekaServiceRibbonApplication.class, args);
}
}
2.5.4 HelloRibbonController、HelloRibbonService
package org.oscar.scd.eureka.service.ribbon.controller;
import org.oscar.scd.eureka.service.ribbon.service.HelloRibbonService;
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
@RequestMapping("/ribbon")
public class HelloRibbonController {
@Autowired
public HelloRibbonService service;
@GetMapping("/print")
public String print(@RequestParam String name) {
return this.service.hiService(name);
}
}
package org.oscar.scd.eureka.service.ribbon.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HelloRibbonService {
@Autowired
public RestTemplate restTemplate;
public String hiService(String name) {
return restTemplate.getForObject("http://eureka-service//print?name=" + name, String.class);
}
}
3. 验证
3.1 创建SpringBoot启动类
前面都没有记录如何创建SpringBoot启动类,这里记录的时候需要通过不同的端口启动两个eureka-service实例,简单记录一下。
3.1.1 EurekaServerSingletonApplication
最简单的方式添加一个SpringBoot启动类型的启动类就行。
3.1.2 EurekaServiceApplication-8762
3.1.3 EurekaServiceApplication-8763
与8762相同,只是修改 Active profiles 为8763
3.1.4 EurekaServiceRibbonApplication
最简单的方式添加一个SpringBoot启动类型的启动类就行。
3.2 启动
依次启动EurekaServerSingletonApplication
EurekaServiceApplication-8762
EurekaServiceApplication-8763
EurekaServiceRibbonApplication
,启动完成后Run Dashboard界面:
3.3 访问服务信息界面
可直接点击上图中Run Dashboard中的8761端口直接访问,也可访问http://localhost:8761/查看,可看到三个eureka服务都注册到注册中心了。
3.4 调用服务
访问eureka-service-ribbon
提供的服务:http://localhost:8764/ribbon/print?name=oscar,多请求两次,返回结果在一下两种中切换,说明负载均衡起作用了。
- 第一次:
- 第二次
4. 思考
- RestTemplate在调用过程中是什么角色
- 有哪些便捷用法
- eureka是否支持除了REST格式还支持其他协议
- Ribbon如何实现负载均衡的
- 还支持哪些负载均衡算法,随机、轮询、加权随机、加权轮询、源地址hash、最小连接数
- 如何切换负载均衡算法
- 还有哪些常用可配置项
5. 补充
5.1 总结
本系列只能做个快速入门,体验一下各个模块的基础表现是怎么样的,后续会先深入的掌握各个组件的使用,对核心功能会学习源码如何实现,思考的问题也会在后面为自己答疑解惑。要深入,要下沉,丰富自己的知识图谱,提高知识转化率。
5.2 资料
优先一手资料,官网 > 权威 > 社区 > 论坛
http://cloud.spring.io/spring-cloud-static/Finchley.SR1/multi/multi_spring-cloud-ribbon.html