美文网首页
dubbo-protocol-rest下attachments如

dubbo-protocol-rest下attachments如

作者: dracula337435 | 来源:发表于2019-06-23 01:28 被阅读0次

    dubboattachments机制用于在业务请求之外传递附加信息,在很多场景下都有应用。本文尝试从源码角度解析rest协议下,attachments如何传递。

    dubbo的attachments机制简介

    dubbo中有attachments机制,在传递业务参数之外还可以传递附加信息,可以理解为像http一样,在报文传送主要信息外,还有报文头可传递附加信息。
    dubboattachments示例为,在consumer端放入:

    RpcContext.getContext().setAttachment("test-attachment-key", "some-msg");
    

    provider端取出:

    Map<String, String> attachments = RpcContext.getContext().getAttachments();
    

    rest下如何传递

    dubbo-protocol-rest可以让dubbo使用rest方式提供和使用服务,同样也支持attachments机制,键值对位于http报文头,日志形如:

    DEBUG org.apache.http.headers - http-outgoing-0 >> GET /restService/sayHello?name=gxk HTTP/1.1
    DEBUG org.apache.http.headers - http-outgoing-0 >> Accept: application/json;charset=UTF-8
    DEBUG org.apache.http.headers - http-outgoing-0 >> Dubbo-Attachments: test-attachment-key=some-msg
    DEBUG org.apache.http.headers - http-outgoing-0 >> Host: 124.126.21.38:8080
    DEBUG org.apache.http.headers - http-outgoing-0 >> Connection: Keep-Alive
    DEBUG org.apache.http.headers - http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.2 (Java/11.0.2)
    DEBUG org.apache.http.headers - http-outgoing-0 >> Accept-Encoding: gzip,deflate
    

    注意其中第3行即为使用http报文头方式传递attachments

    Dubbo-Attachments: test-attachment-key=some-msg
    

    具体到代码实现,见com.alibaba.dubbo.rpc.protocol.rest.RpcContextFilter,源码片段如下:

    public class RpcContextFilter implements ContainerRequestFilter, ClientRequestFilter {
    
        private static final String DUBBO_ATTACHMENT_HEADER = "Dubbo-Attachments";
    
        // 略
    
        @Override
        public void filter(ContainerRequestContext requestContext) throws IOException {
            // 略
            String headers = requestContext.getHeaderString(DUBBO_ATTACHMENT_HEADER);
            if (headers != null) {
                for (String header : headers.split(",")) {
                    int index = header.indexOf("=");
                    if (index > 0) {
                        String key = header.substring(0, index);
                        String value = header.substring(index + 1);
                        if (!StringUtils.isEmpty(key)) {
                            RpcContext.getContext().setAttachment(key.trim(), value.trim());
                        }
                    }
                }
            }
        }
    
        @Override
        public void filter(ClientRequestContext requestContext) throws IOException {
            int size = 0;
            for (Map.Entry<String, String> entry : RpcContext.getContext().getAttachments().entrySet()) {
                // 略
                String attachments = entry.getKey() + "=" + entry.getValue();
                requestContext.getHeaders().add(DUBBO_ATTACHMENT_HEADER, attachments);
            }
        }
    }
    

    两个函数依次为作为服务端和客户端如何处理attachments,可见rest方式下,attachments主要和RpcContext打交道:

    1. 作为服务端,从http报文头中取出Dubbo-Attachments的内容,将形如a=b,c=d的内容放入RpcContext
    2. 作为客户端,从RpcContext中取出所有键值对,放入http报文头Dubbo-Attachments

    另外,在com.alibaba.dubbo.rpc.filter.ContextFilter中,可见将Invocation中的attachments放入了RpcContext,代码片段如下:

    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        Map<String, String> attachments = invocation.getAttachments();
        // 略
        // mreged from dubbox
        // we may already added some attachments into RpcContext before this filter (e.g. in rest protocol)
        if (attachments != null) {
            if (RpcContext.getContext().getAttachments() != null) {
                RpcContext.getContext().getAttachments().putAll(attachments);
            } else {
                RpcContext.getContext().setAttachments(attachments);
            }
        }
        // 略
    }
    

    上述两个组件,RpcContextFilter作用于http请求,回调时机早于ContextFilterdubbofilter

    相关文章

      网友评论

          本文标题:dubbo-protocol-rest下attachments如

          本文链接:https://www.haomeiwen.com/subject/cfzcqctx.html