dubbo
的attachments
機制用于在業(yè)務請求之外傳遞附加信息,在很多場景下都有應用戒职。本文嘗試從源碼角度解析rest
協(xié)議下栗恩,attachments
如何傳遞。
dubbo的attachments機制簡介
dubbo
中有attachments
機制洪燥,在傳遞業(yè)務參數(shù)之外還可以傳遞附加信息磕秤,可以理解為像http
一樣,在報文傳送主要信息外蚓曼,還有報文頭
可傳遞附加信息亲澡。
dubbo
中attachments
示例為钦扭,在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
具體到代碼實現(xiàn)其弊,見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);
}
}
}
兩個函數(shù)依次為作為服務端和客戶端如何處理attachments
,可見rest
方式下梭伐,attachments主要和RpcContext
打交道:
- 作為服務端痹雅,從
http報文頭
中取出Dubbo-Attachments
的內(nèi)容,將形如a=b,c=d
的內(nèi)容放入RpcContext
- 作為客戶端糊识,從
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請求
拌滋,回調(diào)時機早于ContextFilter
等dubbo
的filter
朴沿。