说一说OpenFeign中的一工厂方法实现

2021-04-27  本文已影响0人  天草二十六_简村人

一、CachingSpringLoadBalancerFactory
从类的名字也可以看出来,它是一个具备缓存功能和生成LB的工厂方法。
除了构造函数,核心是create()方法了。
1、缓存是通过ConcurrentReferenceHashMap集合实现,Key值clientName(被调用方的服务名),如果找到了,则返回。

2、如果不存在,则调用组合类SpringClientFactory(也是一个工厂方法)的getClientConfig(clientName)和getLoadBalancer(clientName)「其实前两个方法也是由getInstance(String name, Class<C> type)实现」获取IClientConfig和ILoadBalancer。目的是创建FeignLoadBalancer的子类RetryableFeignLoadBalancer或者FeignLoadBalancer本身。

client = loadBalancedRetryFactory != null ? new RetryableFeignLoadBalancer(lb, config, serverIntrospector,
            loadBalancedRetryFactory) : new FeignLoadBalancer(lb, config, serverIntrospector);
// 其实下面三行代码的本质都是从应用上下文获取相应的对象。
IClientConfig config = this.factory.getClientConfig(clientName);
        ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
        ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class);

public <T> T getInstance(String name, Class<T> type) {
        AnnotationConfigApplicationContext context = getContext(name);
        if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
                type).length > 0) {
            return context.getBean(type);
        }
        return null;
    }

3、把创建好的FeignLoadBalancer对象放到集合缓存里。

this.cache.put(clientName, client);

下面是全部的详细源码

package org.springframework.cloud.openfeign.ribbon;

import java.util.Map;

import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.util.ConcurrentReferenceHashMap;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;

/**
 * Factory for SpringLoadBalancer instances that caches the entries created.
 *
 * @author Spencer Gibb
 * @author Dave Syer
 * @author Ryan Baxter
 * @author Gang Li
 */
public class CachingSpringLoadBalancerFactory {

    private final SpringClientFactory factory;
    private LoadBalancedRetryFactory loadBalancedRetryFactory = null;

    private volatile Map<String, FeignLoadBalancer> cache = new ConcurrentReferenceHashMap<>();

    public CachingSpringLoadBalancerFactory(SpringClientFactory factory) {
        this.factory = factory;
    }

    public CachingSpringLoadBalancerFactory(SpringClientFactory factory, LoadBalancedRetryFactory loadBalancedRetryPolicyFactory) {
        this.factory = factory;
        this.loadBalancedRetryFactory = loadBalancedRetryPolicyFactory;
    }

    public FeignLoadBalancer create(String clientName) {
        FeignLoadBalancer client = this.cache.get(clientName);
        if(client != null) {
            return client;
        }
        IClientConfig config = this.factory.getClientConfig(clientName);
        ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
        ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class);
        client = loadBalancedRetryFactory != null ? new RetryableFeignLoadBalancer(lb, config, serverIntrospector,
            loadBalancedRetryFactory) : new FeignLoadBalancer(lb, config, serverIntrospector);
        this.cache.put(clientName, client);
        return client;
    }

}

二、几个问题
1、值得参考的是它的cache属性的定义。

    private volatile Map<String, FeignLoadBalancer> cache = new ConcurrentReferenceHashMap<>();

一是它用volatile修饰,二是它采用了ConcurrentMap的一个子类。

public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> 

org.springframework.util.ConcurrentReferenceHashMap能指定所存放对象的引用级别,适用于并发下Map的数据缓存。

在jvm满的时候,会回收掉不可达对象和软引用对象

详细请参考
https://cloud.tencent.com/developer/article/1633098?from=information.detail.concurrentreferencehashmap

上一篇下一篇

猜你喜欢

热点阅读