SpringCloud之Ribbon

本文目录

  • 一、使用方法
      • 1、最简单的用法:
      • 2、带配置信息的用法:
      • 3、自定义扩展组件
      • 4、配合Eureka使用
  • 二、Ribbon与RestTemplate
  • 三、问题

Ribbon是什么?美国的一个人名而已。《当幸福来敲门》中Gardner在投资公司接到的第一个大客户就叫Ribbon。而在SpringCloud中,他是一个重要的负载均衡组件,从一堆服务节点中选择一个节点发起请求。

一、使用方法

Demo参见git项目。

1、最简单的用法:

public static void main(String[] args) {ILoadBalancer lb = new BaseLoadBalancer();List servers = new ArrayList();servers.add(new Server("localhost",8080));servers.add(new Server("localhost",8081));servers.add(new Server("localhost",8082));servers.add(new Server("localhost",8083));lb.addServers(servers);for(int i = 0 ; i < 10 ; i ++) {Server server = lb.chooseServer(null);System.out.println(server);}}

2、带配置信息的用法:

通过配置信息加载服务节点

public static void main(String[] args) {//设置服务器列表。和配置到properties里一样ConfigurationManager.getConfigInstance().setProperty("my-client.ribbon.listOfServers","localhost:8081,localhost:8082,localhost:8083,localhost:8084");//该实例是ZoneAwareLoadBalancer 实例BaseLoadBalancer lb = (BaseLoadBalancer)ClientFactory.getNamedLoadBalancer("my-client");IRule rule = new RoundRobinRule();lb.setRule(rule);for(int i = 0 ; i < 10 ; i ++) {Server server = lb.chooseServer(null);System.out.println(server);}}

这种方式涉及到了ribbon的属性配置,
Ribbon相关的配置有两部分,一部分是Ribbon的通用配置。以ribbon.开头,配置ribbon的一些通用组件
ribbon通用配置
另一部分是Ribbon的实例配置。每个ribbon实例可以有不用的一些负载均衡相关策略。这部分配置的格式是.ribbon.=value。其中instance就是ribbon的实例名。

实现类接口配置参数
ILoadBalancer.ribbon.NFLoadBalancerClassName
IRule.ribbon.NFLoadBalancerRuleClassName
IPing.ribbon.NFLoadBalancerPingClassName
ServerList.ribbon.NIWSServerListClassName
ServerListFilter.ribbon.NIWSServerListFilterClassName
手动配置服务节点.ribbon.listOfServers

3、自定义扩展组件

Ribbon中有几个重要的接口,可以通过这些接口,扩展自己的负载均衡策略。例如可以通过自己实现IRule接口,实现自己的服务节点选择策略。

4、配合Eureka使用

以上的节点列表都是在程序中指定的,而在SpringCloud中,这些节点信息是放在Eureka中维护的。
首先,在SpringCloud的配置文件中先配置Eureka地址。上面示例代码中的server节点,都需要从Eureka上获取。之前有记录,这里就不介绍了。
然后,增加Ribbon相关的配置。主要是配置ribbon的通用部分配置。
最后,关于Ribbon的使用方法,以下代码总结了四种常用方法。看注释就知道了。

   private String instanceId = "EurekaDemo";//服务端的应用名/*** 1、通过instance,ribbon会利用负载均衡策略选出一个服务地址进行调用。*/@Resourceprivate LoadBalancerClient loadBalancerClient;@RequestMapping(value="/logInstance",method = RequestMethod.GET)@ResponseBodypublic Object logInstance() {ServiceInstance serviceInstance = loadBalancerClient.choose(instanceId);logger.info("serviceId: " + serviceInstance.getServiceId() + "; service host:" + serviceInstance.getHost()+ ";service port : " + serviceInstance.getPort());return serviceInstance;}/*** 2、启动项上要添加注释@EnableEurekaClient*/@Resourceprivate DiscoveryClient discoveryClient;@ResponseBody@GetMapping(value="/getServerList")public Object getServerList() {List instances = discoveryClient.getInstances(instanceId);for(ServiceInstance instance:instances) {logger.info(JSON.toJSONString(instance));}return instances;}/*** 3、restTemplate做负载均衡核心就是会在RestTemplate中添加个interceptor,从而将instanceId的访问地址转换成负载均衡选出的服务器地址*/@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}@Resourceprivate RestTemplate restTemplate;@RequestMapping(value = "/getSomeUsers", method = RequestMethod.GET)@ResponseBodypublic Object getSomeUsers(@RequestParam int countNum) {logger.info("Ribbon controller test i = " + 1);List users = new ArrayList();for (int i = 0; i < countNum; i++) {User user = new User();user.setUserId("" + i);users.add(user);}String url = "http://"+instanceId+"/user/getSomeUsers";List userRes = restTemplate.postForObject(url, users, ArrayList.class);return userRes;}@RequestMapping(value="/getOneUsers/{id}",method=RequestMethod.GET)@ResponseBodypublic Object getOneUsers(@PathParam("id")String userId) {logger.info("Ribbon controller getOneUsers id = " + userId);User user = new User();user.setUserId(userId);String url = "http://"+instanceId+"/testServe/getOneUsers";User userInfo = restTemplate.postForObject(url, user, User.class);return userInfo;}/*** 4、使用SpringClientFactory构建负载均衡器。*/@Autowiredprivate SpringClientFactory factory;@Bean //注入一个自定义rulepublic IRule getRule() {return new MyRule();}@RequestMapping(value = "/fa", method = RequestMethod.GET)public String factory() {ZoneAwareLoadBalancer lb = (ZoneAwareLoadBalancer)factory.getLoadBalancer("default");//加载的是IOC容器里的RULEString rn1 = lb.getRule().getClass().getName();logger.info("rn1 : "+rn1);Server ser1 = lb.chooseServer();logger.info("ser1 : "+ser1);ZoneAwareLoadBalancer lb2 = (ZoneAwareLoadBalancer)factory.getLoadBalancer(instanceId);//加载的是IOC容器里的RULEString rn2 = lb2.getRule().getClass().getName();logger.info("rn2 : "+rn2);Server ser2 = lb2.chooseServer();logger.info("ser2 : "+ser2);return "please see the console log";}

二、Ribbon与RestTemplate

这其中有意思一点的就是Ribbon结合RestTemplate一起使用。
给RestTemplate加上@LoadBalanced注解后,这个RestTemplate就具备了负载均衡的功能。其实现原理主要是RestTemplate继承的InterceptingHttpAccessor,而这个InterceptingHttpAccessor可以设置一个拦截器列表。这样,在对RestTemplate进行初始化后,可以根据@LoadBalanced注解,给他加上一个Ribbon实例作为拦截器,这样,就可以将 “http://”+instanceId+"/user/getSomeUsers" 这样的请求,转发到instanceId对应的一个服务节点上。例如:“http://localhost:8081/user/getSomeUsers”

三、问题

其实看完SpringCloud之后一直还有个问题没有解决。当使用微服务后,如何在一些非Spring应用中调用微服务呢?例如曾经遇到一个问题,如何在一个Spark计算程序中调用微服务获取外部数据?
这在现在Apache孵化中的Dubbo里,已经非常简单了,但是SpringCloud,还没有弄明白,虽然大致思路还是明白,需要把SpringCloud内部相关的一系列AOP加载过程全部抽取出来,但是一直无法成功。也希望有大牛能给个示例代码。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部