motan學習筆記 一 微博輕量級RPC架構Motan
motan學習筆記 二 motan架構分析
motan學習筆記 三 motan Demo 分析
motan學習筆記 四 motan Demo 之yar 分析
motan學習筆記 五 opentracing學習入門
motan學習筆記 六 opentracing Brave+zipkin實現
發現了yar 這個東西, motan新增了 YarRpcProtocol 這個協議,主要支援php序列化。
來學習下yar協議的具體實現
從代碼中看出,支援exporter,不支援refer 因為其走的http協議,所以php直接rest方式調用就行
@SpiMeta(name = "yar")public class YarRpcProtocol extends AbstractProtocol { private ConcurrentHashMap<String, ProviderMessageRouter> ipPort2RequestRouter = new ConcurrentHashMap<String, ProviderMessageRouter>(); @Override protected <T> Exporter<T> createExporter(Provider<T> provider, URL url) { return new YarExporter<T>(url, provider, this); } @Override protected <T> Referer<T> createReferer(Class<T> clz, URL url, URL serviceUrl) { //TODO throw new MotanFrameworkException("not yet implemented!"); } public ProviderMessageRouter initRequestRouter(URL url, Provider<?> provider) { String ipPort = url.getServerPortStr(); ProviderMessageRouter requestRouter = ipPort2RequestRouter.get(ipPort); if (requestRouter == null) { ipPort2RequestRouter.putIfAbsent(ipPort, new YarMessageRouter()); requestRouter = ipPort2RequestRouter.get(ipPort); } requestRouter.addProvider(provider); return requestRouter; } public void unexport(URL url, Provider<?> provider){ String protocolKey = MotanFrameworkUtil.getProtocolKey(url); String ipPort = url.getServerPortStr(); Exporter<?> exporter = (Exporter<?>) exporterMap.remove(protocolKey); if (exporter != null) { exporter.destroy(); } synchronized (ipPort2RequestRouter) { ProviderMessageRouter requestRouter = ipPort2RequestRouter.get(ipPort); if (requestRouter != null) { requestRouter.removeProvider(provider); } } LoggerUtil.info("yarRpcExporter unexport Success: url={}", url); }}
接著看endpointFactory,具體的實作類別是netty4yar
@SpiMeta(name = "netty4yar")public class Netty4YarEndpointFactory extends AbstractEndpointFactory { @Override protected Server innerCreateServer(URL url, MessageHandler messageHandler) { return new Netty4HttpServer(url, new YarMessageHandlerWarpper(messageHandler)); } @Override protected Client innerCreateClient(URL url) { // TODO throw new MotanFrameworkException("not yet implemented!"); }}
看netty的server的initchannel
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("http-decoder", new HttpRequestDecoder()); ch.pipeline().addLast("http-aggregator", new HttpObjectAggregator(maxContentLength)); ch.pipeline().addLast("http-encoder", new HttpResponseEncoder()); ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler()); ch.pipeline().addLast("serverHandler", handler); } }).option(ChannelOption.SO_BACKLOG, 1024).childOption(ChannelOption.SO_KEEPALIVE, false);
接著看看handler
public class YarMessageHandlerWarpper implements MessageHandler { private YarMessageRouter orgHandler; public YarMessageHandlerWarpper(MessageHandler orgHandler) { if (orgHandler == null) { throw new MotanFrameworkException("messageHandler is null!"); } if (orgHandler instanceof YarMessageRouter) { this.orgHandler = (YarMessageRouter) orgHandler; } else { throw new MotanFrameworkException("YarMessageHandlerWarper can not wrapper " + orgHandler.getClass().getSimpleName()); } } @Override public Object handle(Channel channel, Object message) { FullHttpRequest httpRequest = (FullHttpRequest) message; String uri = httpRequest.getUri(); int index = uri.indexOf("?");// should not be null String requestPath = uri; Map<String, String> attachments = null; if (index > -1) { requestPath = uri.substring(0, index); if (index != uri.length() - 1) { attachments = getAttachMents(uri.substring(index + 1, uri.length())); } } YarResponse yarResponse = null; String packagerName = "JSON"; try { ByteBuf buf = httpRequest.content(); final byte[] contentBytes = new byte[buf.readableBytes()]; buf.getBytes(0, contentBytes); YarRequest yarRequest = new AttachmentRequest(YarProtocol.buildRequest(contentBytes), attachments); yarRequest.setRequestPath(requestPath); yarResponse = (YarResponse) orgHandler.handle(channel, yarRequest); } catch (Exception e) { LoggerUtil.error("YarMessageHandlerWarpper handle yar request fail.", e); yarResponse = YarProtocolUtil.buildDefaultErrorResponse(e.getMessage(), packagerName); } byte[] responseBytes; try { responseBytes = YarProtocol.toProtocolBytes(yarResponse); } catch (IOException e) { throw new MotanFrameworkException("convert yar response to bytes fail.", e); } FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(responseBytes)); httpResponse.headers().set(HttpHeaders.Names.CONTENT_TYPE, "application/x-www-form-urlencoded"); httpResponse.headers().set(HttpHeaders.Names.CONTENT_LENGTH, httpResponse.content().readableBytes()); if (HttpHeaders.isKeepAlive(httpRequest)) { httpResponse.headers().set(HttpHeaders.Names.CONNECTION, Values.KEEP_ALIVE); } else { httpResponse.headers().set(HttpHeaders.Names.CONNECTION, Values.CLOSE); } return httpResponse; } private Map<String, String> getAttachMents(String params) { Map<String, String> map = new HashMap<String, String>(); String[] paramArray = params.split("&"); for (String param : paramArray) { String[] kv = param.split("="); if (kv.length == 2) { map.put(kv[0], kv[1]); } else { LoggerUtil.warn("yar attachment parse fail. uri param:" + param); } } return map; }}