Java tutorial
/** * Copyright 2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.yea.remote.netty.balancing; import java.net.SocketAddress; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import org.springframework.util.StringUtils; import com.yea.core.base.id.UUIDGenerator; import com.yea.core.loadbalancer.AbstractBalancingNode; import com.yea.core.remote.AbstractPoint; import com.yea.core.remote.constants.RemoteConstants; import com.yea.core.remote.exception.RemoteException; import com.yea.core.remote.observer.Observable; import com.yea.core.remote.struct.CallAct; import com.yea.core.remote.struct.CallReflect; import com.yea.core.remote.struct.Header; import com.yea.core.remote.struct.Message; import com.yea.remote.netty.client.promise.AwaitPromise; import com.yea.remote.netty.constants.NettyConstants; import com.yea.remote.netty.exception.WriteRejectException; import com.yea.remote.netty.promise.NettyChannelPromise; import com.yea.remote.netty.send.SendHelper; import com.yea.remote.netty.send.SendHelperRegister; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.DefaultChannelPromise; import io.netty.util.concurrent.GenericFutureListener; import io.netty.util.concurrent.GlobalEventExecutor; /** * * @author yiyongfei * */ public class RemoteClient extends AbstractBalancingNode { private Channel channel = null; private SendHelper nettySend = null; public RemoteClient(Channel channel, AbstractPoint endpoint) { super(endpoint, channel.remoteAddress()); this.channel = channel; } /** * ??? * ???? */ @Override protected boolean resetHystrixHealth() { if (hystrix == 0 && getNettySend().getSendQueue().isEmpty()) { hystrix = 1.0; return true; } return false; } /** * ?Channel??(Write)?? */ @Override protected boolean resetSendHealth() { if (unwrite == 0 && channel.isWritable()) { unwrite = 1.0; return true; } if (unwrite == 1 && !channel.isWritable()) { unwrite = 0.0; return true; } return false; } @SuppressWarnings({ "rawtypes", "unchecked" }) public <T> NettyChannelPromise<T> send(CallAct act, List<GenericFutureListener> listeners, RemoteConstants.MessageType messageType, byte[] sessionID, Object[] messages) throws Exception { if (!this.channel.isWritable()) { throw new WriteRejectException(); } AwaitPromise observer = new AwaitPromise(new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE)); if (listeners != null && listeners.size() > 0) { for (GenericFutureListener listener : listeners) { observer.addListener(listener); } } Observable handle = null; Iterator<Map.Entry<String, ChannelHandler>> itHandle = channel.pipeline().iterator(); while (itHandle.hasNext()) { Map.Entry<String, ChannelHandler> entry = itHandle.next(); if (entry.getValue() instanceof Observable) { handle = (Observable) entry.getValue(); handle.addObserver(sessionID, observer); } } Message nettyMessage = new Message(); Header header = new Header(); header.setType(messageType.value()); header.setSessionID(sessionID); if (act != null) { header.addAttachment(NettyConstants.MessageHeaderAttachment.CALL_ACT.value(), act.getActName()); if (!StringUtils.isEmpty(act.getCallbackName())) { header.addAttachment(NettyConstants.MessageHeaderAttachment.CALLBACK_ACT.value(), act.getCallbackName()); } if (act instanceof CallReflect) { header.addAttachment(NettyConstants.MessageHeaderAttachment.CALL_REFLECT.value(), act); } } else { if (messageType.value() == RemoteConstants.MessageType.SERVICE_REQ.value()) { throw new Exception("?????Act??"); } } header.addAttachment(NettyConstants.MessageHeaderAttachment.HEADER_DATE.value(), new Date()); nettyMessage.setHeader(header); nettyMessage.setBody(messages); try { getNettySend().send(nettyMessage, observer); } catch (Exception ex) { Thread.sleep(200); throw ex; } return observer; } @Override public void ping(int timeout) throws Throwable { if (this.isDown()) { throw new RemoteException("Node[" + this.channel + "]?"); } if (!this.channel.isWritable()) { throw new WriteRejectException(); } byte[] sessionID = UUIDGenerator.generate(); AwaitPromise<Boolean> promise = new AwaitPromise<Boolean>( new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE)); Observable handle = null; Iterator<Map.Entry<String, ChannelHandler>> itHandle = channel.pipeline().iterator(); while (itHandle.hasNext()) { Map.Entry<String, ChannelHandler> entry = itHandle.next(); if (entry.getValue() instanceof Observable) { handle = (Observable) entry.getValue(); handle.addObserver(sessionID, promise); } } Message nettyMessage = new Message(); Header header = new Header(); header.setType(RemoteConstants.MessageType.PING_REQ.value()); header.setSessionID(sessionID); nettyMessage.setHeader(header); channel.writeAndFlush(nettyMessage, promise); promise.awaitObject(timeout); } private SendHelper getNettySend() { if (nettySend == null) { nettySend = SendHelperRegister.getInstance(getChannel()); } return nettySend; } /** * @see com.jbs.core.balancing.hash.BalancingNode#getSocketAddress() */ public SocketAddress getRemoteAddress() { return channel.remoteAddress(); } public SocketAddress getLocalAddress() { return channel.localAddress(); } public Channel getChannel() { return channel; } }