motan學習筆記 四 motan Demo 之yar 分析








發現了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;
    }

}


發佈了111 篇原創文章 · 獲贊 3 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章