dubbo-protocol-rest下attachments如何传递

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

dubbo的attachments机制简介

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

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

provider端取出:

Map 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 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 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如何传递)