博客中代码地址:https://github.com/farliu/farpc.git
在上两章中,我们基于zookeeper实现了dubbo的注册中心。本章是作为服务治理的番外篇讲述,对注册中心的另一种实现方案探讨。也为接下来讲述SPI做好铺垫。
那么本章是基于redis作为存储中间件,实现服务治理,也就是图片中的第1,2,3步,思路跟zookeeper实现方式一致,存储结构也大致相同。使用redis的list类型。想详细了解redis的,请跳转至redis妙用,这里讲述了redis的各种应用场景,以及将遇到的坑。
项目结构介绍
本节涉及博客中代码的module,farpc-registry(服务治理),这章对IRegistrar进行了修改,将init()沉在AbstractRegistrar,在AbstractRegistrar的构造方法中调用init(),防止调用IRegistrar时,忘记调用init(),如下:
1 2 3 4 5 6 7 8 9 10 11
| public interface IRegistrar {
void register(String providerAddress, String service);
String discover(String service); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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。
1 2 3 4 5
| <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.5.0</version> </dependency>
|
然后这里新增了两个类,RedisOparetor、RedisRegistrarImpl,RedisOparetor用来初始化redis连接,RedisRegistrarImpl主要继承AbstractRegistrar来实现IRegistrar。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| 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); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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; } }
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @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。