前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手写dubbo 5-服务治理(redis番外篇)

手写dubbo 5-服务治理(redis番外篇)

作者头像
并发笔记
发布2019-07-19 10:48:47
5580
发布2019-07-19 10:48:47
举报
文章被收录于专栏:并发笔记并发笔记

博客中代码地址:https://github.com/farliu/farpc.git

在上两章中,我们基于zookeeper实现了dubbo的注册中心。本章是作为服务治理的番外篇讲述,对注册中心的另一种实现方案探讨。也为接下来讲述SPI做好铺垫。

那么本章是基于redis作为存储中间件,实现服务治理,也就是图片中的第1,2,3步,思路跟zookeeper实现方式一致,存储结构也大致相同。使用redis的list类型。想详细了解redis的,请跳转至阅读原文,这里讲述了redis的各种应用场景,以及将遇到的坑。

项目结构介绍

本节涉及博客中代码的module,farpc-registry(服务治理),这章对IRegistrar进行了修改,将init()沉在AbstractRegistrar,在AbstractRegistrar的构造方法中调用init(),防止调用IRegistrar时,忘记调用init(),如下:

代码语言:javascript
复制
public interface IRegistrar {

    /**
     * 注册服务
     * @param providerAddress 服务提供者地址
     * @param service 服务
     */
    void register(String providerAddress, String service);

    String discover(String service);
}
代码语言:javascript
复制
public abstract class AbstractRegistrar implements IRegistrar {
    protected static final String FOLDER = "/faregistrys";
    protected static final String SEPARATOR = "/";

    public AbstractRegistrar() {
        String address = Property.Registry.address;
        init(address);
    }

    public String discover(String service) {
        List<String> providers = lookup(service);
        ILoadbalance loadbalance = new RoundLoadBalanceImpl();
        String select = loadbalance.select(providers);
        return select;
    }

    protected abstract void init(String address);

    protected abstract List<String> lookup(String service);
}
redis实现注册中心

使用redis作为注册中心跟zookeeper的逻辑是一样的,所以这章不会像之前那样一步步推理了,直接铺代码了。我们先依赖maven,我们选择jedis操作redis。

代码语言:javascript
复制
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.5.0</version>
</dependency>

然后这里新增了两个类,RedisOparetor、RedisRegistrarImpl,RedisOparetor用来初始化redis连接,RedisRegistrarImpl主要继承AbstractRegistrar来实现IRegistrar。

代码语言:javascript
复制
public class RedisOparetor {
    private static Logger logger = LoggerFactory.getLogger(RedisOparetor.class);
    private static int MAX_ACTIVE = 1024;
    private static int MAX_IDLE = 200;
    private static int MAX_WAIT = 10000;
    private static int TIMEOUT = 10000;
    private static boolean TEST_ON_BORROW = true;
    private static JedisPool jedisPool = null;

    public static void init(String addr) {
        if (jedisPool == null) {
            synchronized (RedisOparetor.class) {
                if (jedisPool == null) {
                    try {
                        String[] split = addr.split(":");
                        String host = split[0];
                        Integer port = Integer.parseInt(split[1]);
                        JedisPoolConfig config = new JedisPoolConfig();
                        config.setMaxTotal(MAX_ACTIVE);
                        config.setMaxIdle(MAX_IDLE);
                        config.setMaxWaitMillis(MAX_WAIT);
                        config.setTestOnBorrow(TEST_ON_BORROW);
                        jedisPool = new JedisPool(config, host, port, TIMEOUT);
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                    }
                }
            }
        }
    }

    public synchronized static Jedis getJedis() {
        try {
            if (jedisPool != null) {
                Jedis resource = jedisPool.getResource();
                return resource;
            } else {
                throw new RuntimeException("call RedisOparetor.getJedis, connection is closed");
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    /***
     * 释放资源
     */
    public static void returnResource(final Jedis jedis) {
        if (jedis != null) {
            jedisPool.returnResource(jedis);
        }
    }
}
代码语言:javascript
复制
public class RedisRegistrarImpl extends AbstractRegistrar {

    public void register(String providerAddress, String service) {
        RedisOparetor.getJedis().lpush(FOLDER + SEPARATOR + service, providerAddress);
    }

    @Override
    protected void init(String address) {
        RedisOparetor.init(address);
    }

    @Override
    public List<String> lookup(String service) {
        List<String> lrange = RedisOparetor.getJedis().lrange(FOLDER + SEPARATOR + service, 0, -1);
        return lrange;
    }
}
测试
代码语言:javascript
复制
@Test
public void redisTest() throws IOException {
    IRegistrar registrar = new RedisRegistrarImpl();
    registrar.register("127.0.0.1:20880", "com.ofcoder.farpc.demo.api.IWelcome");
    System.in.read();
}

@Test
public void test() throws IOException {
    IRegistrar registrar = new RedisRegistrarImpl();
    System.out.println(registrar.discover("com.ofcoder.farpc.demo.api.IWelcome"));
}

------------------------------------
127.0.0.1:20880
总结

其实我没啥好总结的,就是预测一下下一章,下一章讲述的是dubbo值得一吹的SPI。我们使用SPI整合redis、zookeeper。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 并发笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 项目结构介绍
  • redis实现注册中心
  • 测试
  • 总结
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档