In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >
Share
Shulou(Shulou.com)06/01 Report--
In the previous series of articles on the call chain, we have introduced the call chain in detail. I believe you have a basic understanding of the call chain technology.
Expand reading:
Call chain Series (1): interpretation of gluttonous Snakes in UAVStack
Call chain series (2): light call chain implementation
Call chain series (3): how to capture body and header from scratch
In fact, in the process of drawing the call chain, the transfer of the context of the call chain is of great concern. After obtaining the upper-level context, each node generates a new context and passes it back. In the process of transmission, once the context is lost or abnormal, the data of the call chain will be missing and may even be broken.
This article mainly describes some of the implementation details in the context transfer process of the call chain in UAV.
Preface
In the implementation of the call chain, there are mainly the following ways to pass the context of the call chain:
Context transfer from before request processing to after request processing
Context transfer between client calls
Context transfer during invocation between services.
In these three cases, the information and problems encountered in the context transmission process will be different.
In the context transfer process before and after the request processing, the information that needs to be transmitted generally includes traceID, spanID, the time when the request starts and some request parameters. The relevant code may face the problem of asynchronous thread delivery because of asynchronous execution.
In client invocation and inter-service invocation, the context information that needs to be passed generally only includes traceID and spanID. However, the context transfer between client calls may encounter the problem of cross-thread pool delivery, while inter-service calls may encounter the problem of cross-application transmission.
Therefore, we analyze the context passing we are talking about today into the following four scenarios:
Pass in the same thread
Pass across thread pool
Asynchronous thread delivery
Cross-application delivery
To better illustrate these four scenarios, we assume that the following business invocation procedures exist:
Suppose a request first enters service A, initiates a JDBC request in the business code of service A, accesses the data source, and then initiates an http access through httpClient (synchronous, asynchronous) and returns the corresponding result.
The number indicates that there is an acquisition of the context information of the call chain at the point at which it is located. The transfer of the context of the calling chain is involved between most of the adjacent points.
For example, from 2: 00 to 3: 00 is the context transfer before and after the request, from 3: 00 to 4: 00 is the context transfer between two client calls, and from 4: 00 to 5: 00 is the context transfer between services. Below we will explain the process of context transfer between points in different scenarios.
Context passing within the same thread
This kind of scenario is relatively common and the simplest.
Assuming that all the above simulation processes are synchronous operations, and the business code does not involve any thread pool (database connection pool does not affect) and asynchronous operations, then the relevant code of the call chain in Service A will be executed in the same thread.
At this point, I think everyone will think that we can solve the problem by using ThreadLocal. Using ThreadLocal does solve the problem of parameter sharing and passing in the same thread. In UAV, the context transfer between two client calls usually uses ThreadLocal directly (in fact, it is not the native ThreadLocal, which will be described later). The delivery process is as follows:
However, in many cases, asynchronous or commit thread pool operations are often involved in business code, so using ThreadLocal alone cannot meet the corresponding requirements. Let's talk about context passing with thread pool operations and asynchronous requests.
Context transfer across thread pools
For the first time, let's look at the issue of context passing across thread pools.
Suppose that when the JDBC operation is performed in the above business scenario, the current thread is only responsible for submitting the JDBC operation to the thread pool, then the context information will be transferred from 1: 00 to 2: 00, and the cross-thread pool will be encountered. It is impossible to transfer the context information using ThreadLocal.
Of course, some students may say to use InheritableThreadLocal. However, there is no parent-child relationship between the commit thread and the thread pool thread itself, so InheritableThreadLocal cannot complete the context transfer across the thread pool.
In order to solve this problem, we use Ali's open source cross-thread pool ThreadLocal component: transmittable-thread-local (hereinafter referred to as TTL). If you are interested in the implementation, you can learn about https://github.com/alibaba/transmittable-thread-local).
Through this component, the function of ThreadLocal can be enhanced to realize the transmission across thread pools. The following is an example of the use of TTL in github:
TransmittableThreadLocal parent = newTransmittableThreadLocal (); parent.set ("value-set-in-parent"); Runnable task = new Task ("1"); / / additional processing to generate the modified object ttlRunnable Runnable ttlRunnable = TtlRunnable.get (task); executorService.submit (ttlRunnable); / / Task can be read with the value "value-set-in-parent" String value = parent.get ()
As you can see, for TTL to work, you need to change the runnable in the business code to TtlRunnable. In order to achieve zero intrusion into the business code, we add a ClassFileTransformer for some Eexecutor such as ThreadPoolExecutor with the help of the javaagent mechanism, and package the Runnable and Callable submitted to the thread pool into the corresponding TtlRunnable and TtlCallable, so as to complete the context transfer of the cross-thread pool without modifying the business code.
In addition, because TTL has all the features of ThreadLocal, the ThreadLocal used in the context transfer of UAV is TTL.
Third, context transmission in asynchronous threads
After looking at the cross-thread pool operation above, let's take a look at the problem of asynchronous threads.
Suppose that in the above simulation scenario, we send an asynchronous Http request using asynchronous HttpClient. Because it is an asynchronous operation, the 4: 00 code and 7: 00 code (where the context of 7: 00 is acquired from 4: 00 belongs to the context acquisition scenario before and after the request) are actually executed in different threads, resulting in the inability of 7: 00 to obtain the context data put into the ThreadLocal at 4: 00, resulting in the loss of data in the call chain.
In order to solve this problem, we use both bytecode rewriting and dynamic proxy technology in UAV. The key lies in the choice of the target hijacking function, which needs to be able to get the callback object of the asynchronous thread.
Let's take asynchronous HttpClient as an example to introduce the transfer process of asynchronous thread context in UAV.
In asynchronous HttpClient, we hijack the execute () method of the InternalHttpAsyncClient class, which is declared as follows:
In general, async is used by passing in a callback interface object and implementing the corresponding asynchronous logic in callback, or by using the get () method of the returned Future interface object to implement an asynchronous to synchronous operation.
In order to obtain the context of the call chain in the corresponding place, we first generate the context information of the call chain before the method execution by rewriting the bytecode, then do dynamic proxy to the FutureCallback interface, pass the generated context information to the proxy object, and replace the original callback object.
In this way, when the asynchronous request returns to call the callback interface, we actually get our proxy object, and the process of passing the context in the asynchronous thread is completed as follows:
In order to support the asynchronous to synchronous operation through the get () method, we also do a dynamic proxy to the returned Future interface to complete the context transfer.
IV. Cross-application context delivery
After talking about the context transfer process within the application, let's take a look at the context transfer problem across applications.
Cross-application scenarios are also common. In this scenario, the idea of context transmission is to deserialize the context information according to a certain protocol, and then put it into the request transmission message; hijack the request in the downstream service and obtain the information to complete the context transmission. During the whole process, there is no effect on the parsing of the application message.
Common transport protocols such as HTTP protocol, Dubbo's RPC protocol, RocketMQ's MQ protocol and so on. These protocols generally contain structures similar to header information, which are used to represent additional information for this request.
We can just take advantage of this and put the context information into it and transmit it to the downstream service to complete the context transmission.
Let's still use asynchronous HttpClient to introduce the transfer process of UAV across application contexts.
As we said earlier, in asynchronous HttpClient, we hijacked the execute () method. In this method, we can get the HttpAsyncRequestProducer interface object as follows:
Through the generateRequest () method, we can get the request object to be sent for this request, and use the setHeader () method of request to put the context information of the call chain into the Header and send it downstream.
The context here is generally simple, which is basically composed of traceID and spanID strings, and the transmission cost is not high.
As for how to parse the context in the downstream service, it is actually mentioned in the previous call chain series that with the help of UAV's middleware enhancement framework (MOF), the corresponding request object of the request is hijacked at the server, and then directly obtained from its header information.
Other protocols such as RPC or MQ are completed in this way in UAV, but the specific API and hijacking points are different.
For example, RpcContext is used in Dubbo remote calls, and RocketMQ is put into the UserProperty of msg. Interested students can go to UAVStack (https://github.com/uavorg/uavstack)) to see the relevant source code.
Summary
Once you understand the delivery process of these contexts, you can achieve more powerful functionality based on the call chain. In UAV, the function of call chain and log association is realized by hijacking the relevant code of the log input part, obtaining the context of the call chain, and then outputting the traceID to the business log.
You can also try to obtain the context of the call chain in the business code to connect the business data with the call chain data to facilitate data statistics and troubleshooting.
Author: Zhu Wenqiang
Yixin Institute of Technology
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.