Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money

Introduction to the

Some dubbo methods may require non-business attributes such as traceId, userInfo, token, and so on during dubbo application calls, and adding these parameters to the method signature would make the code look a little unelegant. So is there a better way?

The Dubbo framework provides implicit parameter delivery through RpcContext#attachments.

The service consumer can set additional attribute key-value pairs using the rpcContext.getContext ().setAttachment() method, The service provider can get the set additional attribute key-value pairs within the service method via rpcContext.getContext ().getAttachment(). It is usually used for framework integration and is not recommended for passing normal business parameters (for reasons such as code readability).

Usage examples

Set implicit parameters on the service consumer side

@test public void Test () {rpcContext.getContext ().setAttachment("userId", "1"); RpcContext.getContext().setAttachment("traceId", "Hemx4j"); String result = xxxservice. sayHello(" implicit parameter "); System.out.println("result = " + result); }Copy the code

Gets implicit parameters on the service provider side

@override public String sayHello(String name) {Map<String, String> attachments = RpcContext.getContext().getAttachments(); System.out.println("attachments = " + attachments); String userId = RpcContext.getContext().getAttachment("userId"); String traceId = (String) RpcContext.getContext().getAttachment("traceId"); System.out.println("userId = " + userId); System.out.println("traceId = " + traceId); return "Hello, " + name; }Copy the code

The source code parsing

The service consumer binds and passes implicit parameters

On the remote invocation of the service consumer, additional attribute key-value pairs are retrieved from the RpcContext, placed in RpcInvocation#attachments, and then transmitted over the network to the service provider.

org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#invoke

org.apache.dubbo.rpc.RpcInvocation#addAttachments

@Override public Result invoke(final Invocation invocation) throws RpcException { checkWhetherDestroyed(); // binding attachments into invocation. Map<String, String> contextAttachments = RpcContext.getContext().getAttachments(); if (contextAttachments ! = null && contextAttachments.size() ! = 0) { ((RpcInvocation) invocation).addAttachments(contextAttachments); }... return doInvoke(invocation, invokers, loadbalance); } public void addAttachments(Map<String, String> attachments) { if (attachments == null) { return; } if (this.attachments == null) { this.attachments = new HashMap<String, String>(); } this.attachments.putAll(attachments); }Copy the code

The service provider retrieves and recycles implicit parameters

On the service provider, when a remote request is received, the request is intercepted via ContextFilter, the additional attribute key-value pairs from RpcInvocation#attachments are retrieved and set into the RpcContext. Subsequent providers that need to use the attachments value need only obtain it from the RpcContext.

org.apache.dubbo.rpc.filter.ContextFilter#invoke

@Override public Result invoke(Invoker<? Text-align: center; "> < font size = 3pt; text-align: center; text-align: center; String> attachments = invocation.getAttachments(); . // Set key-value pairs to RpcContext if (attachments! = null) { if (RpcContext.getContext().getAttachments() ! = null) { RpcContext.getContext().getAttachments().putAll(attachments); } else { RpcContext.getContext().setAttachments(attachments); }}... try { return invoker.invoke(invocation); } finally {// Empty the RpcContext object of the current thread. Implicit arguments are not passed to the next application rpcContext.removecontext (); RpcContext.removeServerContext(); }}Copy the code