SpringCloud学习笔记(三)——Ribbon
一、restTemplate的使用
我们直接通过实例来说明和理解。
首先新建一个子模块,用来测试restTemplate的使用
在测试的主类中添加如下代码,我们就能够获取百度界面的html文件。
代码如下:
package com.example.resttemplate01; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.web.client.RestTemplate; @SpringBootTest class RestTemplate01ApplicationTests { @Test void contextLoads() { //在java中发送http请求 RestTemplate restTemplate = new RestTemplate(); //这个对象有get、post、put、delete方法,可以返回一个实体或者对象 String url = "https://www.baidu.com"; String result = restTemplate.getForObject(url,String.class); System.out.println(result); } }
执行结果如下:
然后我们尝试访问自己写的接口,在这个项目中新建一个controller,编写一个接口进行测试。
首先我们测试get类型的请求,get类型不需要传递太多的参数。
在测试的主类中新增加一个测试get接口的方法,代码如下:
我们先把整个项目启动起来,这样才能访问到接口,然后运行这个测试方法,会发现相应内容都会成功打印。
接下来我们测试post类型的请求,post类型有两种传参方式,一种是json格式数据,实参需要用json注解来接收,另外一种是表单的形式,可以直接使用实体类型来接收。
首先我们新增一个User的实体类:
我们在新增测试接口。
注意两种接收方式的请求头不一样,json格式的请求头为:
而表单形式的请求头为:
最后我们在测试主类中用restTemplate来访问这几个接口。
以json形式访问代码如下:
@Test void testPost1() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/testpost1"; User user = new User("zhangsan",15,10000D); //这里之所以可以直接传对象,是因为对象在web中传输时会被自动转成json格式 String result = restTemplate.postForObject(url,user,String.class); System.out.println(result); }
以表单形式访问代码如下:
@Test void testPost2() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/testpost2"; //传递表单参数 LinkedMultiValueMap<String,Object> map = new LinkedMultiValueMap<>(); map.add("name","lisi"); map.add("age",15); map.add("salary",15859D); String result = restTemplate.postForObject(url,map,String.class); System.out.println(result); }
都可以实现http的通信。
二、Ribbon的简介
2.1 Ribbon
2.2 负载均衡
三、Ribbon入门
我们这里直接用一个实例来说明Ribbon的使用。
3.1 示例设计图
注意几点:
1.provider1、2和consumer都是Eureka客户端,并且provider1与2是集群关系
2.可以把server端部署到服务器上,这样就不用每次都启动了(具体可以参见上一篇文章的docker部署)
3.2 启动一台server,并建立三台客户端。
首先创建provide1与provide2模块,注意这两个是集群关系。

修改pom文件:
配置文件中增加一些基本配置:
server: port: 8081 spring: application: name: provide eureka: client: service-url: #eureka ????????????,???,?? defaultZone: http://localhost:8761/eureka register-with-eureka: true #????
注意:两个模块中的application.name是一样的,但是端口肯定是不一样的。
然后在两个模块中分别创建接口进行负载均衡测试。
接下来创建一台consumer客户端,然后手动来实现负载均衡,访问provider中的接口。
因为没法选择ribbon依赖,我们先选择这两个依赖,后续再在pm文件中手动添加上ribbon的依赖。
同样需要修改springboot和springcloud的版本,然后再添加上ribbon的依赖,代码如下:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> <version>2.2.9.RELEASE</version> </dependency>
配置文件中代码如下:
server: port: 8083 spring: application: name: consumer eureka: client: service-url: #eureka ????????????,???,?? defaultZone: http://localhost:8761/eureka register-with-eureka: true #????
然后我们修改consumer的主类:
@SpringBootApplication @EnableEurekaClient public class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); } @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
增加一个controller类,这里我们实现了http请求的负载均衡。
这里说明一下:DiscoveryClient是用来做服务发现的,即根据服务id获取到它的IP和端口,Eureka中已经有这个对象了,所以可以直接注入
RestTemplate是用来主动发送http请求的,必须要显示的new或者在IOC容器中新建
之前我们学习RestTemplate的时候,是直接把IP地址和端口写死的,应用场景中必须要根据服务名称手动获取IP和地址,因为对面很有可能是个集群,所以每次的IP地址和端口都会改变
具体代码如下:
@RestController public class TestController { @Autowired private RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; static Random random = new Random(); //自己尝试用RestTemplate写一个负载均衡 //这里说明一下:DiscoveryClient是用来做服务发现的,即根据服务id获取到它的IP和端口,Eureka中已经有这个对象了,所以可以直接注入 //RestTemplate是用来主动发送http请求的,必须要显示的new或者在IOC容器中新建 //之前我们学习RestTemplate的时候,是直接把IP地址和端口写死的,应用场景中必须要根据服务名称手动获取IP和地址,因为对面很有可能是个集群,所以每次的IP地址和端口都会改变 @GetMapping("testBalance") public String testBalance(String serviceId) { //获取服务列表 List<ServiceInstance> instances = discoveryClient.getInstances(serviceId); if (ObjectUtils.isEmpty(instances)) { return "服务列表为空"; } //如果服务列表不为空,先自己做一个负载均衡 ServiceInstance serviceInstance = loadBalance(instances); String host = serviceInstance.getHost(); int port = serviceInstance.getPort(); String url = "http://" + host + ":" + port + "/hello"; System.out.println("本次我调用的是" + url); String forObject = restTemplate.getForObject(url, String.class); System.out.println(forObject); return forObject; } private ServiceInstance loadBalance(List<ServiceInstance> instances) { //拼接 url 去调用 ip:port 先自己实现不用 ribbon ServiceInstance serviceInstance = instances.get(random.nextInt(instances.size())); return serviceInstance; } }
然后我们在浏览器中输入:http://localhost:8083/testBalance?serviceId=provide
会发现交替访问provideA和B。
使用Ribbon来实现负载均衡。
只需要改动consumer中的两个类,其中一个是主类,一个是controller类。
主类中修改代码如下:
controller类中增加如下方法:
@RequestMapping("/testRibbonBalance") public String testRibbonBalance(String serviceId) { //直接用服务名称替换 ip:port String url = "http://" + serviceId + "/info"; String forObject = restTemplate.getForObject(url,String.class); System.out.println(forObject); return forObject; }
注意:一旦加上@LoadBalance这个注解以后,这个restTemplate就交给Ribbon来处理了,然后如果想单独使用restTemplate发送请求的话,需要再新建一个,不能在使用这个了。
然后我们在浏览器中输入:我是服务提供者A!
就会发现A和B交替出现,因为负载均衡算法是轮询问,我们之前自己写的是随机出现的。
四、Ribbon负载均衡的几种算法

五、如何修改负载均衡算法
5.1 单个客户端的调用配置
修改yml配置文件:
provider: #提供者的服务名称,那么访问该服务的时候就会按照自定义的负载均衡算法
ribbon:
NFLoadBalancerRuleClassName:com.netflix.loadbalancer.RandomRule#几种算法的全限定类名
然后测试调用就可以了。
5.2 将所有客户端配置相同负载均衡算法
@Bean public IRule myRule() { //指定调用所有的服务都用此算法 return new RandomRule(); }
六、Ribbon的配置文件和常用配置
ribbon: #全局的设置 eager-load: enabled: false # ribbon 一启动不会主动去拉取服务列表,当实际使用时才去拉取 是否立即加载 http: client: enabled: false # 在 ribbon 最后要发起 Http 的调用调用,我们认为是RestTemplate 完成的,其实最后是 HttpURLConnection 来完成的,这里面设置为 true ,可以把 HttpUrlConnection->HttpClient okhttp: enabled: false #HttpUrlConnection 来完成的,这里面设置为 true ,可以把 HttpUrlConnection->OkHttpClient(也是发 http 请求的,它在移动端的开发用的多) provider: #提供者的服务名称,那么访问该服务的时候就会按照自定义的负载均衡算法 ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改默认负载均衡算法,几种算法的全限定类名 # NFLoadBalancerClassName: #loadBalance 策略 # NFLoadBalancerPingClassName: #ping 机制策略 # NIWSServerListClassName: #服务列表策略 # NIWSServerListFilterClassName: #服务列表过滤策略 ZonePreferenceServerListFilter 默认是优先过滤非一个区的服务列表
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?