1、关于 Ribbon
Spring Cloud Ribbon 是基于 Netflix Ribbon 实现的一套客户端负载均衡的工具。Ribbon 是 Netflix 发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起。Ribbon 客户端组件提供一系列完善的配置项如连接超时、重试等。简单的说,就是在配置文件中列出 Load Balancer(简称LB)后面所有的机器,Ribbon 会自动的基于某种策略(如轮询连接、随机连接等)去连接这些服务器。也很容易使用 Ribbon 实现自定义的负载均衡算法来满足项目中常见的业务环境需求。
2、Ribbon 的作用
LB,即负载均衡(Load Balance),在微服务或分布式集群中经常用的一种应用。负载均衡简单的说就是将用户的请求平均分配到多个服务上,从而达到系统的 HA(也就是我们常说的高可用!!!)。常见的负载均衡有软件 Nginx,LVS,硬件 F5 等,话又说回来,一般没有实力的公司都用不起 F5。相应的在中间件,例如:Dubbo 和 Spring Cloud 中均给我们提供了负载均衡机制,其负载均衡算法都是可以自定义的。
上面说那么多其实就是利用ribbon可以将请求分配到多个服务器,分担每个系统的压力,现在我们开始动手实现一个Demo,程序员请记住这句金科玉律:Talk is cheap, show me the code;
先新建两个provider服务,这里叫service-provider-port(端口号)
贴出provider核心代码如下:
package com.xu.serviceprovider2.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloWorldController {
@Value("${server.port}")
String port;
@RequestMapping("/hi")
public String home(@RequestParam String name) {
return "hi " + name + ", i am from port: " + port;
}
}
具体怎么创建我之前的文章说过了,这里不赘述,以后也不会做赘述,想学习SpringCloud的读者请务必自己动手搭建一个最简单的多模块Springcloud项目,随时备用作为模板修改,我相信你经过大量的修改和测试后,SpringCloud学习才会有乐趣和真的能达到事半功倍的效果,这里我直接贴出我的消费端代码和截图
package com.xu.serviceconsumer.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
public String hiService(String name)
{
return restTemplate.getForObject("http://SERVICE-HELLO/hi?name=" + name, String.class);
}
}
接下来我们看看我们在启动类里做了什么配置:
可以看到,我们的RestTemplate在初始化时候加了一个注解@LoadBalanced,英文不差的同学应该知道这个单词的大概意思就是负载均衡的意思
package com.xu.serviceconsumer.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
public String hiService(String name)
{
return restTemplate.getForObject("http://SERVICE-HELLO/hi?name=" + name, String.class);
}
}
Service部分我们已经定义好了,我们开始在Controller中调用试试看
下面贴出我的Controller代码,请只关注上图截图部分的代码即可
package com.xu.serviceconsumer.controller;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.xu.serviceconsumer.service.HelloService;
import com.xu.serviceconsumer.service.UserFeignClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
@RestController
public class HelloControler {
private static final Logger LOGGER = LoggerFactory.getLogger(HelloControler.class);
@Autowired
private HelloService helloService;
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private UserFeignClient userFeignClient;
@RequestMapping(value = "/hi")
public String hi(@RequestParam String name) {
return helloService.hiService(name);
}
@RequestMapping(value = "/hello")
public String hello(@RequestParam String name) {
return userFeignClient.getName(name);
}
@RequestMapping(value = "/log-instance")
public Object logInstance() {
ServiceInstance serviceInstance = this.loadBalancerClient.choose("SERVICE-HELLO");
LOGGER.info("{}:{}:{}", serviceInstance.getServiceId(),
serviceInstance.getHost(),serviceInstance.getPort());
JSONObject object1 = new JSONObject();
object1.put("ServiceId",serviceInstance.getServiceId());
object1.put("Host",serviceInstance.getHost());
object1.put("Port",serviceInstance.getPort());
return object1.toJSONString();
}
}
我们打开浏览器输入http://localhost:8767/hello?name=Ronnie访问一下我们的请求试试,看他到底调用了哪些服务
既然是负载均衡,那么我们肯定要多调用几次,看看他们是不是分别调用了不同的服务,刷新浏览器再次得到结果如下
端口8763和8764分别是我们的两个同名服务不同的端口,说明请求的确分别请求了两个同名的服务,实现了负载均衡
好了,这次的课程就到这里,有不清楚的读者请及时留言尽快答复,拜拜