public void doSubscribe(final URL url, final NotifyListener listener) { String service = RedisRegistryUtil.toServicePath(url, root); RedisRegistryNotifier notifier = notifiers.get(service); if (notifier == null) { RedisRegistryNotifier newNotifier = new RedisRegistryNotifier(service, this); notifiers.putIfAbsent(service, newNotifier); notifier = notifiers.get(service); if (notifier == newNotifier) { notifier.start(); } } boolean success = false; RpcException exception = null; for (Map.Entry<String, JedisPool> entry : jedisPools.entrySet()) { JedisPool jedisPool = entry.getValue(); try { Jedis jedis = jedisPool.getResource(); try { if (service.endsWith(Constants.ANY_VALUE)) { admin = true; Set<String> keys = jedis.keys(service); if (keys != null && keys.size() > 0) { Map<String, Set<String>> serviceKeys = RedisRegistryUtil.getServiceKeys(keys, root); for (Set<String> sk : serviceKeys.values()) { doNotify(jedis, sk, url, Arrays.asList(listener)); } } } else { doNotify( jedis, jedis.keys(service + Constants.PATH_SEPARATOR + Constants.ANY_VALUE), url, Arrays.asList(listener)); } success = true; break; // 只需读一个服务器的数据 } finally { jedisPool.returnResource(jedis); } } catch (Throwable t) { // 尝试下一个服务器 exception = new RpcException( "Failed to subscribe service from redis registry. registry: " + entry.getKey() + ", service: " + url + ", cause: " + t.getMessage(), t); } } if (exception != null) { if (success) { logger.warn(exception.getMessage(), exception); } else { throw exception; } } }
private void deferExpired() { for (Map.Entry<String, JedisPool> entry : jedisPools.entrySet()) { JedisPool jedisPool = entry.getValue(); try { Jedis jedis = jedisPool.getResource(); try { RedisRegistryUtil.publishToJedis(jedis, getRegistered(), root, expirePeriod); if (admin) { clean(jedis); } if (!replicate) { break; // 如果服务器端已同步数据,只需写入单台机器 } } finally { jedisPool.returnResource(jedis); } } catch (Throwable t) { logger.warn( "Failed to write provider heartbeat to redis registry. registry: " + entry.getKey() + ", cause: " + t.getMessage(), t); } } }
public AbstractRedisRegistry(URL url) { super(url); RedisRegistryUtil.assertNotAnyHost(url); GenericObjectPoolConfig config = RedisRegistryUtil.genericObjectPoolConfig(url); List<String> addresses = RedisRegistryUtil.getAddresses(url); for (String address : addresses) { JedisPool jedisPool = RedisRegistryUtil.initJedisPoolAndCheck(url, config, address); jedisPools.put(address, jedisPool); } this.replicate = RedisRegistryUtil.getReplicate(url); this.reconnectPeriod = url.getParameter( Constants.REGISTRY_RECONNECT_PERIOD_KEY, Constants.DEFAULT_REGISTRY_RECONNECT_PERIOD); this.root = RedisRegistryUtil.getGroup(url); this.expirePeriod = url.getParameter(Constants.SESSION_TIMEOUT_KEY, Constants.DEFAULT_SESSION_TIMEOUT); this.expireFuture = expireExecutor.scheduleWithFixedDelay( new Runnable() { public void run() { try { deferExpired(); // 延长过期时间 } catch (Throwable t) { // 防御性容错 logger.error( "Unexpected exception occur at defer expire time, cause: " + t.getMessage(), t); } } }, expirePeriod / 2, expirePeriod / 2, TimeUnit.MILLISECONDS); }
private void doNotify( Jedis jedis, Collection<String> keys, URL url, Collection<NotifyListener> listeners) { if (keys == null || keys.size() == 0 || listeners == null || listeners.size() == 0) { return; } long now = System.currentTimeMillis(); List<URL> result = new ArrayList<URL>(); List<String> categories = Arrays.asList(url.getParameter(Constants.CATEGORY_KEY, new String[0])); String consumerService = url.getServiceInterface(); for (String key : keys) { if (!Constants.ANY_VALUE.equals(consumerService)) { String prvoiderService = RedisRegistryUtil.toServiceName(key, root); if (!prvoiderService.equals(consumerService)) { continue; } } String category = RedisRegistryUtil.toCategoryName(key); if (!categories.contains(Constants.ANY_VALUE) && !categories.contains(category)) { continue; } Map<String, String> values = jedis.hgetAll(key); List<URL> urls = RedisRegistryUtil.getUrlsForDoNotify(url, now, values); if (urls.isEmpty()) { urls.add(RedisRegistryUtil.setUrlProperties(url, key, category, root)); } result.addAll(urls); if (logger.isWarnEnabled()) { logger.warn("redis notify: " + key + " = " + urls); } } if (result == null || result.size() == 0) { return; } for (NotifyListener listener : listeners) { notify(url, listener, result); } }
public void doRegister(URL url) { String key = RedisRegistryUtil.toCategoryPath(url, root); String value = url.toFullString(); String expire = String.valueOf(System.currentTimeMillis() + expirePeriod); boolean success = false; RpcException exception = null; for (Map.Entry<String, JedisPool> entry : jedisPools.entrySet()) { JedisPool jedisPool = entry.getValue(); try { Jedis jedis = jedisPool.getResource(); try { jedis.hset(key, value, expire); jedis.publish(key, Constants.REGISTER); success = true; if (!replicate) { break; // 如果服务器端已同步数据,只需写入单台机器 } } finally { jedisPool.returnResource(jedis); } } catch (Throwable t) { exception = new RpcException( "Failed to register service to redis registry. registry: " + entry.getKey() + ", service: " + url + ", cause: " + t.getMessage(), t); } } if (exception != null) { if (success) { logger.warn(exception.getMessage(), exception); } else { throw exception; } } }
// 监控中心负责删除过期脏数据 private void clean(Jedis jedis) { RedisRegistryUtil.clean(jedis, root); }