Ribbon 是springcloud 主要组件之一,起到服务调用和负载均衡的作用,其底层封装在 eureka 的客户端和feign组件中,今天只讲使用,后续会讲源码和原理。
1、jar 包的引入:其jar包 包含于 eureka 客户端包里:在上几篇的基础上 这里就 不需要重复引入了。
2、引入RestTemplate配置类 里面注入RestTemplate的方法上面添加注解@LoadBalanced ,@Bean
@Bean
@LoadBalanced //起到负载均衡作用
RestTemplate restTemplate() {
return new RestTemplate();
}
//负载均衡的配置
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
//启动方法
public static void main(String[] args) {
SpringApplication.run(TestLoadBalanceMain.class,args);
}
3、客户端 Controller 方法创建
public static String SERVIER_NAME = "micro-order-no";
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/queryU")
public List queryU(HttpServletRequest request) {
log.info(Thread.currentThread().getName() + "========queryContents=========");
//该方法通过负载算法。选择一个服务调用。
List results = restTemplate.getForObject("http://"
+ SERVIER_NAME + "/user/queryContent", List.class);
return results;
}
4、服务提供方 Controller 方法创建
@RequestMapping("/queryContent")
public List queryContent(HttpServletRequest request) {
logger.info(""+this.hashCode());
ConsultContent c = new ConsultContent();
c.setContent("sdsdsdsdsdsdd");
List list = new ArrayList<>();
list.add(c);
return list;
}
5、三个微服务启动后调用结果
6、客户端 controller 可以起多个服务,调用时根据负载算法选择其中一个服务调用。小伙伴可以自己测试一下。
7、Ribbon 的Api 有多种类型 比如 get ,post 等等,我在这贴出来大家可以认真看看:
Get 请求 :关注请求的一些信息
getForEntity:此方法有三种重载形式,分别为:
getForEntity(String url, Class
getForEntity(String url, Class
getForEntity(String url, Class
getForEntity(URI url, Class
注意:此方法返回的是一个包装对象 ResponseEntity
想拿到返回类型需要使用这个包装类对象的 getBody()方法
getForObject:此方法也有三种重载形式,这点与 getForEntity 方法相同:
getForObject(String url, Class
getForObject(String url, Class
getForObject(String url, Class
getForObject(URI url, Class
注意:此方法返回的对象类型为 responseType 传入类型
Post 请求 :主要关注请求结果信息
post 请求和 get 请求都有*ForEntity 和*ForObject 方法,其中参数列表有些不同,除了这两个
方法外,还有一个 postForLocation 方法,其中 postForLocation 以 post 请求提交资源,并返
回新资源的 URI
postForEntity:此方法有三种重载形式,分别为:postForEntity(String url, Object request, Class
postForEntity(String url, Object request, Class
postForEntity(URI url, Object request, Class
注意:此方法返回的是一个包装对象 ResponseEntity
想拿到返回类型需要使用这个包装类对象的 getBody()方法
postForObject:此方法也有三种重载形式,这点与 postForEntity 方法相同:
postForObject(String url, Object request, Class
postForObject(String url, Object request, Class
postForObject(URI url, Object request, Class
注意:此方法返回的对象类型为 responseType 传入类型
postForLocation:此方法中同样有三种重载形式,分别为:
postForLocation(String url, Object request, Object... uriVariables)
postForLocation(String url, Object request, Map
postForLocation(URI url, Object request)
注意:此方法返回的是新资源的 URI,相比 getForEntity、getForObject、postForEntity、
postForObject 方法不同的是这个方法中无需指定返回类型,因为返回类型就是 URI,通过
Object... uriVariables、Map
部分代码
8、ribbon 负载均衡算法:ribbon中具体实现负载均衡的策略是通过IRule这个接口来实现的,接口实现结构图
默认的负载均衡策略是:ZoneAvoidanceRule:区域权衡策略。然后我们可以通过配置来使用其他的负载均衡策略。
9、代码中配置ribbon 属性:
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.*;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/*
这是在代码中配置ribbon,也可以在bootstrap配置文件中配置,二选一
* 注意:这个类最好不要出现在启动类的@ComponentScan扫描范围
* 如果出现在@ComponentScan扫描访问,那么这个配置类就是每个服务共用的配置了
* */
@Configuration
public class RibbonLoadBalanceMicroOrderConfig {
//如果指定调用某个服务,可以加上服务名;配置文件中配置也是类似这样
@RibbonClientName
private String name = "micro-order";
@Bean
@ConditionalOnClass
public IClientConfig defaultClientConfigImpl() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.loadProperties(name);
config.set(CommonClientConfigKey.MaxAutoRetries,2);
config.set(CommonClientConfigKey.MaxAutoRetriesNextServer,2);
config.set(CommonClientConfigKey.ConnectTimeout,2000);
config.set(CommonClientConfigKey.ReadTimeout,4000);
config.set(CommonClientConfigKey.OkToRetryOnAllOperations,true);
return config;
}
/*
* 判断服务是否存活
* 不建议使用
* */
@Bean
public IPing iPing() {
//这个实现类会去调用服务来判断服务是否存活
return new PingUrl();
}
@Bean
public IRule ribbonRule() {
//线性轮训
new RoundRobinRule();
//可以重试的轮训
new RetryRule();
//根据运行情况来计算权重
new WeightedResponseTimeRule();
//过滤掉故障实例,选择请求数最小的实例
new BestAvailableRule();
return new RandomRule();
}
}
10、Ribbon 选择性配置文件中配置:
ribbon.client.name=micro-order
#点对点直连测试配置
# 关闭ribbon访问注册中心Eureka Server发现服务,但是服务依旧会注册。
#true使用eureka false不使用:服务类表是否从eureka 中来
ribbon.eureka.enabled=true
spring.cloud.loadbalancer.retry.enabled=true
#指定调用的节点,和 ribbon.eureka.enabled=true 二选一配置;这种方式不建议使用,灵活性不好。
#micro-order.ribbon.listOfServers=localhost:8001
#单位ms ,请求连接超时时间
ribbon.ConnectTimeout=1000
#单位ms ,请求处理的超时时间
ribbon.ReadTimeout=3000
#接口幂等性思想,是否重试所有的接口
ribbon.OkToRetryOnAllOperations=false
#切换实例的重试次数
ribbon.MaxAutoRetriesNextServer=2
#对当前实例的重试次数 当Eureka中可以找到服务,但是服务连不上时将会重试
ribbon.MaxAutoRetries=2
#负载均衡的算法配置
ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
#验证服务是否存活的配置
ribbon.NFLoadBalancerPingClassName=com.netflix.loadbalancer.PingUrl
11、其实Ribbon 也可以自己脱离springCloud单独使用:
依赖jar
/*
* ribbon作为调用客户端,可以单独使用
* */
@Test
public void test1() {
try {
ConfigurationManager.getConfigInstance().setProperty("myClients.ribbon.listOfServers","localhost:8001,localhost:8002");
RestClient client = (RestClient)ClientFactory.getNamedClient("myClients");
HttpRequest request = HttpRequest.newBuilder().uri(new URI("/user/queryContent")).build();
for (int i = 0; i < 10; i++) {
HttpResponse httpResponse = client.executeWithLoadBalancer(request);
String entity = httpResponse.getEntity(String.class);
System.out.println(entity);
}
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
这样也可以调用,小伙伴可以亲自测试一下,有不懂的地方及时留言!下一篇我们讲解Hystrix 的实战使用,敬请期待!!!