Review the directory

  • The business scenario | synchronous implementation: kill Redis in seconds kill function of practice
  • Design patterns | a word understand design patterns
  • Apache SkyWalking | SkyWalking advanced play
  • Apache SkyWalking | SkyWalking Java plug-in contribution to practice
  • A distributed job scheduling | HOME LINK distributed operation platform (recommended)

The introduction

SkyWalking Java Plug-in Contribution Practice: Based on SkyWalking 6.0.0-ga-snapshot, this article will take writing the SkyWalking Java Agent plug-in for Redis client as an example, and share with you the process of contributing PR. The SkyWalking Java Agent plugin will be useful to you.

Basic concept

OpenTracing and SkyWalking link modules have several important semantic concepts.

  • Span: can be understood as a method call, a block call, or an RPC/ database access. Any program access with a full time cycle can be considered a SPAN. Important properties in a SkyWalking Span object

    attribute The name of the note
    component component The component name of a plug-in, for example, Lettuce, see ComponentsDefine.Class.
    tag The label K-v structure, key Tags, key see Tags.Class.
    peer For the resources If the DB component is used, record cluster information.
    operationName The operation name If span=0, operationName will search the drop-down list.
    layer According to On the link page, see SpanLayer.class.
  • Trace: Call chain, implicitly defined by the Span belonging to it. A Trace can be considered as a directed acyclic graph (DAG) composed of multiple spans. In SkyWalking link module, you can see that Trace is composed of multiple Trace segments belonging to it.

  • Trace Segment :Segment is a concept in SkyWalking that should include all the scope of each request in a single OS process, typically language-based, single-threaded. It consists of a number of spAs belonging to the operation of this thread.

Core API

Cross-process ContextCarrier core API

  • To achieve distributed tracing, cross-process tracing needs to be bound, and the entire context process should be propagated. That’s ContextCarrier’s job.
  • Here are the steps to implement cross-process propagation:
    • On the client side, create a new empty ContextCarrier and put all ContextCarrier messages into HTTP Heads, Dubbo attachments, or Kafka Messages.
    • The ContextCarrier is passed to the server through a service invocation.
    • On the server side, retrieve all ContextCarrier messages in the heads, attachments, or Messages of the corresponding component. Bind the link information between the server and client.

Cross-thread ContextSnapshot core API

  • In addition to cross-process, cross-thread support is also required, such as asynchronous threads (in-memory message queues) and batch processing, which are common in Java, and cross-process and cross-thread are very similar in that context is propagated. The only difference is that no cross-thread serialization is required.
  • Here are the steps to implement cross-thread propagation:
    • Get the ContextSnapshot object using ContextManager# capture.
    • Let child threads access the ContextSnapshot in any way, either through method parameters or carried by existing parameters.
    • Use ContextManager#continued in the child thread.

For detailed core API knowledge, please read the Plug-in Development Guide – Chinese Version.

Plug-in practice

Lettuce operates the redis code

@PostMapping("/ping")
public String ping(HttpServletRequest request) throws ExecutionException, InterruptedException {
    RedisClient redisClient = RedisClient.create("redis://" + "127.0.0.1" + ": 6379");
    StatefulRedisConnection<String, String> connection0 = redisClient.connect();
    RedisAsyncCommands<String, String> asyncCommands0 = connection0.async();
    AsyncCommand<String, String, String> future = (AsyncCommand<String, String, String>)asyncCommands0.set("key_a"."value_a");
    future.onComplete(s -> OkHttpClient.call("http://skywalking.apache.org"));
    future.get();
    connection0.close();
    redisClient.shutdown();
    return "pong";
}
Copy the code

Plug-in source architecture

The Oracle wrapper for Redis is similar to Redisson Redisson, with the aim of implementing an easy-to-use Java Redis client with no learning curve. Therefore, if you want to intercept Redis operation first, you need to learn the source code of the corresponding client.

Design the plug-in

Code implementation

PR url: Support lettuce Plugin

Problems encountered in practice

  • Multithreaded programming using debug breakpoints can change links to synchronization. It is recommended to use run mode to add logs or remote debug to solve this problem.
  • Multithreaded programming requires the cross-thread ContextSnapshot core API or the link will break.
  • CompleteableCommand onComplete method sometimes performed synchronously, this and internal mechanism, sometimes don’t separate threads.
  • If the compiled version of the plug-in is 1.7+, you need to place the plug-in in the optional plug-in. Because the Sniffer supports version 1.6.

The plugin is compatible with

In order to obtain the final compatible version of the plug-in, we need to use Docker to test all the plug-in versions, and the specific steps are as follows:

  • Write test Cases: Follow how to document how to write test cases.
  • Provide automated test cases. For example, Redisson plugin TestCase
  • Make sure that the local versions of several popular plug-ins run locally as expected.
  • After providing automated test cases and submitting tests in CI, the plug-in submitter approves your plug-in.
  • The final result is a complete plug-in test report.

Pull Request

Submit a PR

When submitting your PR, you need to briefly describe your design for the plug-in so that you can discuss completing the CodereView with the community of contributors.

Applying for automated tests

Once the test cases are written, you can apply for automated tests that will generate a plug-in compatible version of the report in your PR.

The plugin documentation

Plugin documentation needs to be updated: Supported-list.md Plugin information support.

If a plug-in is optional, add the corresponding description in the agent-option-plugins optional plug-in document.

annotation

Lettuce is a completely non-blocking Redis client, built using Netty, providing reactive, asynchronous and synchronous data access. For details, please read lettuce. IO.

OpenTracing is a cross-programming language standard. For details, see OpenTracing Semantic Standards.

Span: org. Apache. Skywalking. Apm. Agent. The core. The context. Trace. AbstractSpan interface defines all span method needs to be done;

Redisson is a very easy-to-use Java Redis client that has no learning curve and doesn’t need to know any Redis commands to start using it. For details, read redisson.org.