美文网首页
spring cloud ribbon

spring cloud ribbon

作者: 奋斗的韭菜汪 | 来源:发表于2020-07-23 18:00 被阅读0次

1、解析配置中的服务列表:spring-cloud-ribbon-order.ribbon.listOfServers
2、基于负载均衡算法实现请求的分发
Ribbon负载均衡实现方式(本质相同:在服务请求到目标服务前增加了Interceptor拦截器实现负载均衡):
1、@LoadBalanced(在http请求对象(RestTemplate、httpClient、okHttp等)加上该注解), LoadBalanced本质是一个@Qualifier的注解(所有加了@LoadBalanced注解的请求对象都会被扫描到加载到LoadBalancerAutoConfiguration类中的restTemplates对象中,因为restTemplates加了LoadBalanced注解)

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({RestTemplate.class})
@ConditionalOnBean({LoadBalancerClient.class})
@EnableConfigurationProperties({LoadBalancerRetryProperties.class})
public class LoadBalancerAutoConfiguration {
    @LoadBalanced
    @Autowired(
        required = false
    )
    private List<RestTemplate> restTemplates = Collections.emptyList();
    @Autowired(
        required = false
    )

2、LoadBalancerClinet(在起始服务中注入LoadBalancerClinet对象)

核心api:ILoadBalancer、IRule(负载均衡规则:轮询,随机,时间响应权重(定时任务在不断的发送请求,根据相应时间,根据特定算法))、Iping(定时任务每10s检查服务存活状态(心跳机制))、ServerList(定时任务,每30s执行一次更新服务列表)

//Qualifier注解的作用:标记作用,这里表示将所有加了Qualifier注解的bean,加载到testList中
@Qualifier
@Autowired
private List<TestClass>  testList;

详见源码:

Ribbon负载均衡策略源码(轮询实现):
AbstractServerPredicate类

    private int incrementAndGetModulo(int modulo) {
        for (;;) {
            int current = nextIndex.get();
            int next = (current + 1) % modulo;
            if (nextIndex.compareAndSet(current, next) && current < modulo)
                return current;
        }
    }

心跳机制底层实现:
通过定时任务向指定服务发送http请求,若请求返回状态码为200,则表示当前服务未存活状态,否则为非存活状态

    public boolean isAlive(Server server) {
        String urlStr = "";
        if (this.isSecure) {
            urlStr = "https://";
        } else {
            urlStr = "http://";
        }

        urlStr = urlStr + server.getId();
        urlStr = urlStr + this.getPingAppendString();
        boolean isAlive = false;
        HttpClient httpClient = new DefaultHttpClient();
        HttpUriRequest getRequest = new HttpGet(urlStr);
        String content = null;

        try {
            HttpResponse response = httpClient.execute(getRequest);
            content = EntityUtils.toString(response.getEntity());
            isAlive = response.getStatusLine().getStatusCode() == 200;
            if (this.getExpectedContent() != null) {
                LOGGER.debug("content:" + content);
                if (content == null) {
                    isAlive = false;
                } else if (content.equals(this.getExpectedContent())) {
                    isAlive = true;
                } else {
                    isAlive = false;
                }
            }
        } catch (IOException var11) {
            var11.printStackTrace();
        } finally {
            getRequest.abort();
        }

        return isAlive;
    }

关于@LoadBalanced源码解析:
LoadBalancerAutoConfiguration系统配置类中包含以下代码:

    @LoadBalanced
    @Autowired(required = false)
    private List<RestTemplate> restTemplates = Collections.emptyList();

@LoadBalanced包含@Qualifier会将所有直接或者间接加了@Qualifier注解的Bean加载到restTemplates数组中
springcloud ribbon负载均衡策略配置(随机):
springboot-eureka-clent.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
延伸:
Java之Collections.emptyList()、emptySet()、emptyMap()的作用和好处以及要注意的地方]

先说明一下好处有哪些:
1,如果你想 new 一个空的 List ,而这个 List 以后也不会再添加元素,那么就用 Collections.emptyList() 好了。
new ArrayList() 或者 new LinkedList() 在创建的时候有会有初始大小,多少会占用一内存。
每次使用都new 一个空的list集合,浪费就积少成多,浪费就严重啦,就不好啦
2,为了编码的方便。
比如说一个方法返回类型是List,当没有任何结果的时候,返回null,有结果的时候,返回list集合列表。
那样的话,调用这个方法的地方,就需要进行null判断。使用emptyList这样的方法,可以方便方法调用者。返回的就不会是null,省去重复代码。

注意的地方:
这个空的集合是不能调用.add(),添加元素的。因为直接报异常。因为源码就是这么写的:直接抛异常。

哦,Collections里面没这么写,但是EmptyList继承了AbstractList这个抽象类,里面简单实现了部分集合框架的方法。
这里面的add方法最后调用的方法体,就是直接抛异常。
throw new UnsupportedOperationException();
使用场景:
web开发中经常使用rest + json的技术组合来进行前后端交互,那么当前端调用一个接口时,接口有可能需要返回一个空的集合给到前端,比如你根据某个条件查数据库得不到数据时,那么此时Collections.emptyXXX()就非常合适了

相关文章

网友评论

      本文标题:spring cloud ribbon

      本文链接:https://www.haomeiwen.com/subject/sctnhktx.html