当raft节点运行在一个进程内时,可以通过代理方式复用同一个连接。 这个类在一个进程内只有一个实例,然后传入启用代理的Raft.Agent使用。 另外,ProxyDispatch 的代码也写在这里,只是一个静态函数。
| 20 | * 另外,ProxyDispatch 的代码也写在这里,只是一个静态函数。 |
| 21 | */ |
| 22 | public class ProxyAgent extends Service { |
| 23 | public static final String eProxyAgentName = "Zeze.Raft.ProxyAgent"; |
| 24 | private final int rpcTimeout; |
| 25 | |
| 26 | public ProxyAgent(int rpcTimeout) { |
| 27 | super(eProxyAgentName, (Config)null); |
| 28 | this.rpcTimeout = rpcTimeout; |
| 29 | getSocketOptions().setOutputBufferMaxSize(100 * 1024 * 1024); |
| 30 | getSocketOptions().setInputBufferMaxProtocolSize(100 * 1024 * 1024); |
| 31 | |
| 32 | AddFactoryHandle(ProxyRequest.TypeId_, new Service.ProtocolFactoryHandle<>( |
| 33 | ProxyRequest::new, |
| 34 | this::ProcessProxyRequest, |
| 35 | TransactionLevel.None |
| 36 | )); |
| 37 | } |
| 38 | |
| 39 | /** |
| 40 | * 把代理请求派发到指定的raft中执行。 |
| 41 | * |
| 42 | * @param r ProxyRequest |
| 43 | */ |
| 44 | private long ProcessProxyRequest(ProxyRequest r) throws Exception { |
| 45 | var agent = agents.get(r.Argument.getRaftName()); |
| 46 | if (null == agent) |
| 47 | return Procedure.ProviderNotExist; |
| 48 | var client = agent.getClient(); |
| 49 | var outFactoryHandle = new OutObject<Service.ProtocolFactoryHandle<?>>(); |
| 50 | var p = Protocol.decode(client::findProtocolFactoryHandle, ByteBuffer.Wrap(r.Argument.getRpcBinary()), outFactoryHandle); |
| 51 | if (null == p) |
| 52 | return Procedure.NotImplement; |
| 53 | |
| 54 | if (!(p instanceof ProxyableRpc<?, ?>)) |
| 55 | throw new RuntimeException("not a proxyable rpc."); |
| 56 | |
| 57 | var proxyable = (ProxyableRpc<?, ?>)p; |
| 58 | proxyable.setProxyRequest(r); |
| 59 | // 重新派发一次,有点浪费线程切换,以后再考虑优化。 |
| 60 | client.dispatchProtocol(p, outFactoryHandle.value); |
| 61 | return 0; |
| 62 | } |
| 63 | |
| 64 | public static class ConnectorEx extends Connector { |
| 65 | private final ConcurrentHashMap<String, Agent.ConnectorProxy> proxys = new ConcurrentHashMap<>(); |
| 66 | |
| 67 | public ConnectorEx(String host, int port) { |
| 68 | super(host, port, true); |
| 69 | } |
| 70 | |
| 71 | public ConnectorEx(String host, int port, boolean autoConnect) { |
| 72 | super(host, port, autoConnect); |
| 73 | } |
| 74 | |
| 75 | public Agent.ConnectorProxy getConnectorProxy(String name) { |
| 76 | return proxys.computeIfAbsent(name, __ -> new Agent.ConnectorProxy(name, this)); |
| 77 | } |
| 78 | } |
| 79 | /** |
nothing calls this directly
no outgoing calls
no test coverage detected