SpringCloud踩坑笔记 | 服务消费(Ribbon)

 上次介绍了《SpringCloud踩坑笔记 | 简单的注册中心集群》,今天在上一次的基础上来简单的看下服务消费,学习如何去消费服务提供者的接口。

一、RestTemplate

服务提供者添加方法

服务提供者(eureka-client)的DcController添加一个接口:

@GetMapping("/test")
public String test() {
    return "eureka-client8001 test ok.";
}

首先导入依赖


    
        org.springframework.boot
        spring-boot-starter-actuator
    
    
        org.springframework.cloud
        spring-cloud-starter-eureka
        1.3.1.RELEASE
    

添加配置

spring.application.name=eureka-consumer
server.port=6001
#不注册自己
eureka.client.register-with-eureka=false
eureka.client.serviceUrl.defaultZone=http://localhost7001:7001/eureka/,http://localhost7002:7002/eureka/

创建测试类\配置类\启动类

@RestController
public class ServiceController {

    private static String http_url = "http://localhost:8001";

    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/consumer")
    public String consumer() {
        String url = http_url + "/test";
        System.out.println("eureka consumer --> "+ url);
        return restTemplate.getForObject(url, String.class);
    }
}

@Configuration
public class ConfigBean {
    @Bean
    public RestTemplate getRestTempalte(){
        return new RestTemplate();
    }
}

@SpringBootApplication
@EnableDiscoveryClient
public class Consumer01 {
	public static void main(String[] args) {
			SpringApplication.run(Consumer01.class, args);
	}
}

 依次运行eureka-server、eureka-client、eureka-consumer,浏览器中输入http://localhost:6001/consumer 即可看到调用了getService方法。
 来看RestTemplate的源码,其实就是个HTTP远程调用:
SpringCloud踩坑笔记 | 服务消费(Ribbon)_第1张图片
 我们可以看出来这样调用十分的繁琐,还需要手动拼接地址,不是特别好,我们来看看Ribbon是怎么做的


二、Ribbon

 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。它是一个基于HTTP/TCP的客户端负载均衡器。它可以通过在客户端中配置ribbonServerList来设置服务端列表去轮询访问以达到均衡负载的作用。  Ribbon是进程式(LB)负载均衡,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

导入Ribbon依赖
在上述工程中导入Ribbon依赖,不需要重新创建工程


    org.springframework.cloud
    spring-cloud-starter-ribbon
    1.4.7.RELEASE

修改eureka-consumer中的ConfigBean

@Bean
@LoadBalanced //开启了负载均衡
public RestTemplate getRestTempalte(){
    return new RestTemplate();
}

修改eureka-consumer中的ServiceController类:

@RestController
public class ServiceController {

    private static String http_url = "http://eureka-client";

    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/consumer")
    public String consumer2() {
        String url = http_url + "/test";
        System.out.println("eureka consumer --> "+ url);
        return restTemplate.getForObject(url, String.class);
    }
}

浏览器运行http://localhost:6001/consumer即可调用eureka-client中的方法。
可以看出只需要服务名称就可以,不需要域名和端口

此时负载均衡不明显,我们再创建一个服务提供者,和eureka-client8001一样的

DcController只保留test接口

@GetMapping("/test")
public String test() {
    return "eureka-client8002 test ok.";
}

修改启动类和配置文件:

spring.application.name=eureka-client
server.port=8002

eureka.instance.instance-id=springcloud-client8002
eureka.client.service-url.defaultZone=http://localhost7001:7001/eureka/,http://localhost7002:7002/eureka/

info.compay.name=iFillDream
info.auth.name=RickSun

注意服务提供者的spring.application.name要一样

依次启动eureka-server7001、eureka-server7002、eureka-client8001、eureka-client8002、eureka-consumer

浏览器运行http://localhost:6001/consumer即可调用eureka-client中的方法。效果就是以下两种结果顺序出现即轮询

第一种结果:eureka-client8001 test ok.
第二种结果:eureka-client8002 test ok.

在消费者eureka-consumer中的CofingBean中开启了负载均衡即@LoadBalanced注解

从IRule接口源码中我们可以看到负载的几种方式:

1.RoundRobinRule-轮询(默认)
2.AvailabilityFilteringRule-根据服务是否死掉或者服务处于高并发来分配权重  
3.RandomRule-随机访问
4.RetryRule-轮询后如果获取失败,则在指定时间内重试
……

那么如何更换负载均衡的规则呢?以随机规则举例

在eureka-consumer的ConfigBean中添加配置:

@Bean
public IRule myRule(){
    return new RandomRule();
}

重启eureka-consumer后运行效果就是随机访问服务提供者了~

可以看出这里还是使用了自带的几种方式,那么如何自定义呢?

先删掉上述的myRule()配置;

自定义的不允许出现在主程序上下文@ComponentScan中,需要放在不重复的包中

在eureka-consumer主程序的上一级包目录中创建ruleconfig包,再创建MyRule配置类:

/**
 * 自定义负载均衡规则
 * 每个服务调用5次,5次后轮询下一个服务
 * @author RickSun && iFillDream
 */
@Configuration
public class MyRule extends AbstractLoadBalancerRule {

    private int count = 0;//调用次数

    private int currentIndex = 0;//当前服务下标

    @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        } else {
            Server server = null;
            while(server == null) {
                if (Thread.interrupted()) {
                    return null;
                }
                //所有存活的服务
                List upList = lb.getReachableServers();
                //所有服务
                List allList = lb.getAllServers();
                //所有服务的总数
                int serverCount = allList.size();
                if (serverCount == 0) {
                    return null;
                }

                if(count < 5){
                    count++;
                    server = upList.get(currentIndex);
                }else {
                    count = 0;
                    currentIndex++;
                    if (currentIndex >= serverCount){
                        currentIndex = 0;
                    }
                }

                if (server == null) {
                    Thread.yield();
                } else {
                    if (server.isAlive()) {
                        return server;
                    }
                    server = null;
                    Thread.yield();
                }
            }
            return server;
        }
    }

    public Server choose(Object key) {
        return this.choose(this.getLoadBalancer(), key);
    }

    public void initWithNiwsConfig(IClientConfig clientConfig) {
    }

}

在eureka-consumer的main方法上添加以下注解:

@RibbonClient(name="eureka-client",configuration = MyRule.class)

重启eureka-consumer后运行效果就是自定义的负载均衡的规则了~
以上就是ribbon的基础教程了

统一首发平台为微信公众号iFillDream,搜索关注第一时间掌握最新推送

你可能感兴趣的:(笔记)