dubbo-router

1、引入 jar 包

<dependencies>
     <dependency>
         <groupId>org.apache.curator</groupId>
         <artifactId>curator-recipes</artifactId>
         <version>4.2.0</version>
     </dependency>
     <dependency>
         <groupId>org.apache.dubbo</groupId>
         <artifactId>dubbo</artifactId>
     </dependency>
</dependencies>

2、新建工具类 ZookeeperClients

public class ZookeeperClients {

    private final CuratorFramework client;

    private static ZookeeperClients INSTANCE;

    static {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
        CuratorFramework client = CuratorFrameworkFactory.newClient("101.132.167.18:2181",retryPolicy);
        INSTANCE = new ZookeeperClients(client);
    }

    private ZookeeperClients(CuratorFramework client){
        this.client = client;
    }

    public static CuratorFramework client(){
        return INSTANCE.client;
    }
}

3、新建 ReadyRestartInstances

public class ReadyRestartInstances implements PathChildrenCacheListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(ReadyRestartInstances.class);

    private static final String LISTEN_PATHS = "/lagou/dubbo/restart/instances";

    private final CuratorFramework zkClient;

    // 当节点变化时,给这个集合赋值,重启机器的信息列表
    private volatile Set<String> restartInstance = new HashSet<>();

    private ReadyRestartInstances(CuratorFramework zkClient){
        this.zkClient = zkClient;
    }

    public static ReadyRestartInstances create(){
        final CuratorFramework zookeeperClient = ZookeeperClients.client();
        try{

            // 检查监听路径是否存在
            final Stat stat = zookeeperClient.checkExists().forPath(LISTEN_PATHS);
            // 如果监听路径不存在,则创建
            if(stat == null){
                zookeeperClient.create().creatingParentsIfNeeded().forPath(LISTEN_PATHS);
            }
        }catch (Exception e){
            e.printStackTrace();
            LOGGER.error("确保基础路径存在");
        }
        final ReadyRestartInstances instances = new ReadyRestartInstances(zookeeperClient);
        // 创建一个 NodeCache
        PathChildrenCache nodeCache = new PathChildrenCache(zookeeperClient,LISTEN_PATHS,false);
        // 给节点缓存对象加入监听
        nodeCache.getListenable().addListener(instances);
        try{
            nodeCache.start();
        }catch (Exception e){
            e.printStackTrace();
            LOGGER.error("启动监听失败");
        }
        return instances;
    }
    /** 返回应用名 和 主机拼接后的字符串 **/
    private String buildApplicationAndInstanceString(String applicationName,String host){
        return applicationName + "_" + host;
    }
    /** 增加重启实例的配置信息方法 **/
    public void addRestartingInstance(String applicationName,String host) throws Exception{
        zkClient.create().creatingParentsIfNeeded().forPath(LISTEN_PATHS + "/" + buildApplicationAndInstanceString(applicationName,host));
    }

    /** 删除重启实例的配置信息方法 **/
    public void deleteRestartingInstance(String applicationName,String host) throws Exception{
        zkClient.delete().forPath(LISTEN_PATHS + "/" + buildApplicationAndInstanceString(applicationName,host));
    }

    /** 判断节点信息是否存在于 restartInstances **/
    public boolean hasRestartingInstance(String applicationName,String host){
        return restartInstance.contains(buildApplicationAndInstanceString(applicationName,host));
    }

    @Override
    public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
        // 查询出监听路径下所有的目录配置信息
        final List<String> restartingInstances = zkClient.getChildren().forPath(LISTEN_PATHS);
        // 给 restartInstances;
        if(CollectionUtils.isEmpty(restartingInstances)){
            this.restartInstance = Collections.emptySet();
        }else{
            this.restartInstance = new HashSet<>(restartingInstances);
        }
    }
}

4、新建 RestartingInstanceRouter

public class RestartingInstanceRouter implements Router {

    private final ReadyRestartInstances instances;

    private final URL url;

    public RestartingInstanceRouter(URL url){
        this.url = url;
        this.instances = ReadyRestartInstances.create();
    }

    @Override
    public URL getUrl() {
        return url;
    }

    @Override
    public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
        // 如果没有在重启列表中,才会加入到后续调用列表
        return invokers.stream().filter(i->!instances.hasRestartingInstance(
                i.getUrl().getParameter("remote.application"),
                i.getUrl().getIp())).collect(Collectors.toList());
    }

    @Override
    public boolean isRuntime() {
        return false;
    }

    @Override
    public boolean isForce() {
        return false;
    }

    @Override
    public int getPriority() {
        return 0;
    }
}

5、新建 RestartingInstanecRouterFactory

@Activate
public class RestartingInstanecRouterFactory implements RouterFactory {
    @Override
    public Router getRouter(URL url) {
        return new RestartingInstanceRouter(url);
    }
}

6、配置文件:

包名:META-INF/dubbo

文件名:org.apache.dubbo.rpc.cluster.RouterFactory

restartInstances=com.deppon.util.RestartingInstanecRouterFactory

7、启动类:ServerRestartMain

public class ServerRestartMain {
    public static void main(String[] args) throws Exception {
        // ReadyRestartInstances.create().addRestartingInstance("server-provider","xxx.xx.xx.xx");
        ReadyRestartInstances.create().removeRestartingInstance("server-provider","xxx.xx.xx.xx");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值