private void deferExpired() { for (Map.Entry<String, JedisPool> entry : jedisPools.entrySet()) { JedisPool jedisPool = entry.getValue(); try { Jedis jedis = jedisPool.getResource(); try { for (Node node : new HashSet<Node>(getRegistered())) { String key = NodeRegistryUtils.getNodeTypePath(clusterName, node.getNodeType()); if (jedis.hset( key, node.toFullString(), String.valueOf(SystemClock.now() + expirePeriod)) == 1) { jedis.publish(key, Constants.REGISTER); } } if (lock.acquire(jedis)) { clean(jedis); } if (!replicate) { break; // 如果服务器端已同步数据,只需写入单台机器 } } finally { jedis.close(); } } catch (Throwable t) { LOGGER.warn( "Failed to write provider heartbeat to redis registry. registry: " + entry.getKey() + ", cause: " + t.getMessage(), t); } } }
private void clean(Jedis jedis) { // /LTS/{集群名字}/NODES/ Set<String> nodeTypePaths = jedis.keys(NodeRegistryUtils.getRootPath(appContext.getConfig().getClusterName()) + "/*"); if (CollectionUtils.isNotEmpty(nodeTypePaths)) { for (String nodeTypePath : nodeTypePaths) { // /LTS/{集群名字}/NODES/JOB_TRACKER Set<String> nodePaths = jedis.keys(nodeTypePath); if (CollectionUtils.isNotEmpty(nodePaths)) { for (String nodePath : nodePaths) { Map<String, String> nodes = jedis.hgetAll(nodePath); if (CollectionUtils.isNotEmpty(nodes)) { boolean delete = false; long now = SystemClock.now(); for (Map.Entry<String, String> entry : nodes.entrySet()) { String key = entry.getKey(); long expire = Long.parseLong(entry.getValue()); if (expire < now) { jedis.hdel(nodePath, key); delete = true; if (LOGGER.isWarnEnabled()) { LOGGER.warn( "Delete expired key: " + nodePath + " -> value: " + entry.getKey() + ", expire: " + new Date(expire) + ", now: " + new Date(now)); } } } if (delete) { jedis.publish(nodePath, Constants.UNREGISTER); } } } } } } }
@Override protected void doRegister(Node node) { String key = NodeRegistryUtils.getNodeTypePath(clusterName, node.getNodeType()); String expire = String.valueOf(SystemClock.now() + expirePeriod); boolean success = false; NodeRegistryException exception = null; for (Map.Entry<String, JedisPool> entry : jedisPools.entrySet()) { JedisPool jedisPool = entry.getValue(); try { Jedis jedis = jedisPool.getResource(); try { jedis.hset(key, node.toFullString(), expire); jedis.publish(key, Constants.REGISTER); success = true; if (!replicate) { break; // 如果服务器端已同步数据,只需写入单台机器 } } finally { jedis.close(); } } catch (Throwable t) { exception = new NodeRegistryException( "Failed to register node to redis registry. registry: " + entry.getKey() + ", node: " + node + ", cause: " + t.getMessage(), t); } } if (exception != null) { if (success) { LOGGER.warn(exception.getMessage(), exception); } else { throw exception; } } }
public boolean isTimeout() { long diff = SystemClock.now() - this.beginTimestamp; return diff > this.timeoutMillis; }
/** 异步请求应答封装 */ public class ResponseFuture { private final int opaque; private final long timeoutMillis; private final AsyncCallback asyncCallback; private final long beginTimestamp = SystemClock.now(); private final CountDownLatch countDownLatch = new CountDownLatch(1); // 保证信号量至多至少只被释放一次 private final SemaphoreReleaseOnlyOnce once; // 保证回调的callback方法至多至少只被执行一次 private final AtomicBoolean executeCallbackOnlyOnce = new AtomicBoolean(false); private volatile RemotingCommand responseCommand; private volatile boolean sendRequestOK = true; private volatile Throwable cause; public ResponseFuture( int opaque, long timeoutMillis, AsyncCallback asyncCallback, SemaphoreReleaseOnlyOnce once) { this.opaque = opaque; this.timeoutMillis = timeoutMillis; this.asyncCallback = asyncCallback; this.once = once; } public void executeInvokeCallback() { if (asyncCallback != null) { if (this.executeCallbackOnlyOnce.compareAndSet(false, true)) { asyncCallback.operationComplete(this); } } } public void release() { if (this.once != null) { this.once.release(); } } public boolean isTimeout() { long diff = SystemClock.now() - this.beginTimestamp; return diff > this.timeoutMillis; } public RemotingCommand waitResponse(final long timeoutMillis) throws InterruptedException { this.countDownLatch.await(timeoutMillis, TimeUnit.MILLISECONDS); return this.responseCommand; } public void putResponse(final RemotingCommand responseCommand) { this.responseCommand = responseCommand; this.countDownLatch.countDown(); } public long getBeginTimestamp() { return beginTimestamp; } public boolean isSendRequestOK() { return sendRequestOK; } public void setSendRequestOK(boolean sendRequestOK) { this.sendRequestOK = sendRequestOK; } public long getTimeoutMillis() { return timeoutMillis; } public AsyncCallback getAsyncCallback() { return asyncCallback; } public Throwable getCause() { return cause; } public void setCause(Throwable cause) { this.cause = cause; } public RemotingCommand getResponseCommand() { return responseCommand; } public void setResponseCommand(RemotingCommand responseCommand) { this.responseCommand = responseCommand; } public int getOpaque() { return opaque; } @Override public String toString() { return "ResponseFuture [responseCommand=" + responseCommand + ", sendRequestOK=" + sendRequestOK + ", cause=" + cause + ", opaque=" + opaque + ", timeoutMillis=" + timeoutMillis + ", invokeCallback=" + asyncCallback + ", beginTimestamp=" + beginTimestamp + ", countDownLatch=" + countDownLatch + "]"; } }