Summary
Sermant is a cloud-native agentless service mesh based on Java bytecode enhancement technology. It is non-intrusive, plug-inable and high-performance. Through the Sermant core framework, plug-ins for various service management purposes can be easily developed, including load balancing, flow control, label routing, label transparent transmission, etc. In this article, we use a case to explain how to develop a plug-in that counts the call duration based on Sermant and use it for deployment in the production environment.
In the first chapter, we explain how to quickly develop a plug-in and demonstrate the complete code development process. We will focus on 1) how to develop a main module to enhance the code for the application; 2) how to package and build plug-ins.
In Chapter 2, we will explain how to perform service governance through the Sermant package developed in Chapter 1. We will demonstrate that the host application mounts the Sermant Agent through the premain method and verifies the enhancement effect.
In Chapter 3, we will introduce the high-level functions provided by Sermant. Key points include: 1) Monitoring Sermant Agent through Sermant Backend; 2) How to use the Sermant log function for log printing to avoid class conflicts in the log function while taking into account the observability of the abnormal status of the sidecar; 3) How to use dynamic configuration functions Adjust Agent runtime behavior in real time.
1. Plug-in Development
In this chapter, we will completely demonstrate the process of developing service governance plug-ins using the Sermant framework from scratch based on the plug-in development template officially provided by Sermant.
The main task that this template plug-in needs to implement is to intercept and enhance the controller interface method of the host application and calculate the method execution time.
Next, let’s start the code path of plug-in development!
Sermant officially provides template code for plug-in development. Execute the following Maven instructions to pull:
$ mvn archetype:generate -DarchetypeGroupId=com.huaweicloud.sermant -DarchetypeArtifactId=sermant-template-archetype -DarchetypeVersion=1.2.0 -DgroupId=com.huaweicloud.sermant -Dversion=1.2.0 -Dpackage=com.huaweicloud -DartifactId=first-plugin
For specific implementation steps and details, please refer to the Sermant official website to create the first plug-in document. The template code pre-designs the project structure and pom file configuration for plug-in development, so we can better focus on the implementation of plug-in functions. The code shown below was developed based on this template. We also provide our developed sample code in the first-plugin-demo of Sermant-example.
1.1 Plug-in main module development
The plug-in main module is the main implementation of the plug-in, and developers need to declare the plug-in’s enhancement logic in this module.
The plug-in main module needs to determine which classes of the host application to intercept. In this article, the intercepted classes of the host application are as follows:
package com.huaweicloud.template; @RestController public class Controller { @RequestMapping("sayHello") public void sayHello(String name) throws InterruptedException { System.out.println("hello " + name); Thread.sleep(5); } }
The main module of the plug-in needs to complete the enhancement logic that calculates the time-consuming execution of the sayHello method, so we first need to intercept the sayHello method of the Controller class, and then perform pre- and post-enhancement calculations on the method in the interceptor.
Create the com.huawei.sermant.template package in the template-plugin module. The classes created in this section are all located in this package.
1) Create the TemplateDeclarer class, which inherits from the com.huaweicloud.sermant.core.plugin.agent.declarer.AbstractPluginDeclarer class. You need to override the getClassMatcher method and getInterceptDeclarers method of the parent class. The class name and method name used to declare bytecode enhanced interception, and the corresponding interceptor. The code implementation details are as follows:
public class TemplateDeclarer extends AbstractPluginDeclarer { @Override public ClassMatcher getClassMatcher() { // Match the classes that need to be intercepted. There are multiple matching methods. Here we use the fully qualified name of the class to match. return ClassMatcher.nameEquals("com.huaweicloud.template.Controller" ); } @Override public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { // Return the InterceptDeclarer array. Each InterceptDeclarer determines the method and Interceptor it needs to intercept. return new InterceptDeclarer[]{ // Match the methods that need to be intercepted. There are multiple matching methods. Here, the method name is used for matching. InterceptDeclarer.build(MethodMatcher.nameEquals("sayHello"), new TemplateInterceptor()) }; } }
The ClassMatcher class and the MethodMatcher class have multiple matching methods. You can check the bytecode enhancement documentation on the Sermant official website.
2) Create the TemplateInterceptor class, which needs to implement the com.huaweicloud.sermant.core.plugin.agent.interceptor.Interceptor interface, and rewrite the before, after, and onThrow methods of the interface to achieve pre-enhancement and post-interception points respectively. Set enhancement and exception handling code logic. The code implementation details are as follows:
public class TemplateInterceptor implements Interceptor { private static final String START_TIME = "startTime"; @Override public ExecuteContext before(ExecuteContext context) { context.setLocalFieldValue(START_TIME, System.currentTimeMillis()); System.out.println("The time when the recorded method started running"); return context; } @Override public ExecuteContext after(ExecuteContext context) { long endTime = System.currentTimeMillis(); long elapsedTime = endTime - (long) context.getLocalFieldValue(START_TIME); System.out.println("Method takes time:" + elapsedTime + "milliseconds"); return context; } @Override public ExecuteContext onThrow(ExecuteContext context) { return context; } }
We record the start time of the intercepted method execution in the before method, calculate the execution time of the intercepted method in the after method and print it to the console.
3) Add the SPI configuration of the enhanced declaration, add the META-INF/services directory to the resources directory under template/template-plugin in the project, and create a directory named com.huaweicloud.sermant.core.plugin.agent.declarer in it. .PluginDeclarer’s SPI file and add the class name of the bytecode enhanced declaration class to it:
com.huaweicloud.sermant.template.TemplateDeclarer
At this point, the code logic development of the main module of the plug-in is completed. We have implemented the interception of the target class and enhanced the methods of the intercepted class.
1.2 Plug-in packaging and building
Execute the maven command in the template directory to package and build the template plug-in:
mvn clean package
After the build is completed, the agent/ directory will be generated. The specific file structure is as follows:
. ├── common ├── config Sermant configuration file ├──core ├── god ├── implemant ├──Application.jar host application, which can be replaced by your own developed application ├── sermant-agent.jar Sermant Agent product, used for mounting and use by host applications └── pluginPackage └── template ├── config plug-in configuration file ├── plugin plug-in main module └── service plug-in service module
Now that we have completed a simple plug-in that can calculate the time taken by intercepted methods, we will start to show the effect of the plug-in.
2. Sermant Agent Use
2.1 Start Sermant Agent
Sermant enables the dynamic configuration service by default. Modify the config.properties file in the config directory to turn off the dynamic configuration service:
# Dynamically configure service switches agent.service.dynamic.config.enable=false
Enter the product directory agent/ built in Chapter 1.2, and start the Sermant Agent in premain mode by configuring the -javaagent directive for the host service:
java -javaagent:sermant-agent.jar -jar Application.jar
The console prints the following output, indicating that the Sermant Agent is successfully started in premain mode.
[2023-1024T17:26:49.049] [INFO] Loading god library into BootstrapClassLoader. [2023-10-24T17:26:49.153] [INFO] Building argument map by agent arguments. [2023-10-24T17:26:49.161] [INFO] Loading core library into SermantClassLoader. [2023-10-24T17:26:49.162] [INFO] Loading sermant agent, artifact is: default [2023-10-24T17:26:49.740] [INFO] Load sermant done, artifact is: default
Sermant Agent can also perform mounting while the host application is running through the agentmain method. For more details about the use of Sermant Agent, please refer to the Sermant Agent User Manual document on the Sermant official website.
2.2 Verification
The host application has successfully mounted the Sermant Agent. In this section we will verify whether the plug-in enhancement logic takes effect.
Execute the following command to initiate a get request for the host application interface service:
curl http://127.0.0.1:8080/sayHello?name=lihua
The output printed by the host application console is as follows:
The time when the method execution started has been recorded hello lihua Method takes: 20 milliseconds ECHO: Best wish to you!
It can be seen that the Sermant Agent successfully intercepted the classes of the host application and executed the enhanced logic.
3. Sermant Advanced functions
3.1 Sermant Backend
Sermant Backend includes Sermant data processing back-end module and front-end information display module, aiming to provide runtime observability capabilities for Sermant. Currently, it mainly includes functions such as Sermant Agent heartbeat information, reception and display of reported events, and webhook push.
Sermant Backend works with Sermant Agent. The Sermant Agent is mounted in the host application. As a data sender, it can regularly send the current Sermant Agent’s heartbeat data (service name, host name, instance ID, version number, IP, timestamp, plug-in mounting information) and event data ( Sermant Agent start and stop, core service start and stop, bytecode enhancement, log data, etc.)
Backend is a non-essential component. Users can deploy it on demand and obtain the Backend component by downloading the release package of Sermant-1.2.0. Unzip the release package, enter the sermant-agent/server/sermant directory and execute the following command to start Sermant Backend:
java -jar sermant-backend-1.2.0.jar
Access the address http://127.0.0.1:8900/ through the browser. If you see the following page, it means that Sermant Backend is started successfully;
Sermant Agent needs to configure the parameters of the Agent when using Backend. Modify the config.properties file in the agent (product directory built in Chapter 1)/config directory.
The configuration items need to be modified as:
# Enable heartbeat service switch agent.service.heartbeat.enable=true # Turn on the unified gateway service switch agent.service.gateway.enable=true
Refer to Section 2.1 to start the Sermant Agent. You can see the started Sermant Agent and mounted template plug-in information on the Backend front-end page:
For more details about Backend, please refer to the Sermant Backend User Manual document on the official Sermant website.
3.2 Log function
Logs are an indispensable capability in program development. Through logs, you can quickly find out the status of the program when it is running and the problems encountered.
JavaAgent products are prone to conflicts with host application classes and log configuration conflicts when using log classes. The log system built by Sermant solves this problem. The Sermant log system is built on JUL & logback, providing a complete, flexible configuration, and class conflict-avoiding log tool for plug-in development. The log system provided by Sermant can be fully integrated with the host microservice from configuration to execution. isolation. In addition, combined with the Sermant Backend component, the Sermant log system can provide unified collection and reporting of abnormal events.
Now we need to record the execution time of the intercepted method in the log. This section will demonstrate how to use the logging system provided by Sermant.
3.2.1 Add log
We define a private static constant LOGGER in the TemplateInterceptor class of the main module of the plug-in, which is used for log construction under this class.
// Sermant log class private static final Logger LOGGER = LoggerFactory.getLogger();
Next, we use logging in the after method of this class to record the running time of the intercepted method. The level of this log is INFO.
LOGGER.info("Method time-consuming: " + elapsedTime);
The Sermant log system can record logs of various levels (TRACE, DEBUG, INFO, WARN, ERROR) to achieve different levels of monitoring of program operation.
For more details, please refer to the Sermant official website log function documentation.
3.2.2 Log demo
Start Sermant and call the interface of the host application according to the method in Chapter 2:
curl http://127.0.0.1:8080/sayHello?name=lihua
Go to the logs/sermant/core/app/xxxx-xx-xx directory to view the Sermant log. “xxxx-xx-xx” is the time when the log was recorded. You can see that the method’s time consumption is successfully recorded in the log file.
[INFO] [com.huaweicloud.sermant.template.TemplateInterceptor] [after:45] [http-nio-8080-exec-1] Method takes: 20
3.2.3 Exception log reporting
Warn and error level logs collected uniformly by the Sermant log system can be uploaded to Sermant Backend for observation. We will manually print the exception log and observe it through Backend.
Print a warn-level log in the before method of the TemplateInterceptor class of the plug-in’s main module, and print an error-level log in the after method:
LOGGER.warning("warning message"); LOGGER.severe("error message");
Modify the config.properties file in the config directory to enable event reporting related configurations:
# Event system switch event.enable=true # Warn level log event reporting switch event.offerWarnLog=true # Error level log event reporting switch event.offerErrorLog=true
Start Sermant and call the interface of the host application according to the method in Chapter 2:
curl http://127.0.0.1:8080/sayHello?name=lihua
Go to the Sermant Backend front-end page to see the reported exception information:
3.3 Dynamic configuration
3.3.1 Add dynamic configuration
Sermant provides dynamic configuration functions and currently supports Zookeeper, Nacos and Kie as configuration centers. The dynamic configuration function allows Sermant to perform configuration management and monitoring operations on the configurations issued by the dynamic configuration center to achieve rich and diverse service governance capabilities. This section takes Zookeeper as an example to demonstrate how to use Sermant’s dynamic configuration service to add a switch for executing enhanced logic to this plug-in.
First, add a Map field to the TemplateInterceptor class in the main module of the plug-in to simulate the switch state. ENABLE_KEY is the name of the switch, and set the default state of the switch to true:
private static final Map<String, Boolean> CONFIG_MAP = new HashMap<>(); private static final String ENABLE_KEY = "enable"; { //The default state of the switch is true CONFIG_MAP.put(ENABLE_KEY, true); }
Then add switches in the before method and after method:
if (!CONFIG_MAP.get(ENABLE_KEY)) { System.out.println("Do not execute enhanced logic"); return context; }
Next, we need to dynamically modify the status of the switch, add the dynamic configuration service field, obtain the dynamic configuration service class instance and register a listener to monitor the corresponding node changes in Zookeeper:
//Get dynamic configuration service class instance private final DynamicConfigService dynamicConfigService = ServiceManager.getService(DynamicConfigService.class); // Get the yaml parser provided by the Sermant framework private final YamlConverter converter = OperationManager.getOperation(YamlConverter.class); { dynamicConfigService.addConfigListener("template-config", "sermant/template-plugin", new DynamicConfigListener() { @Override public void process(DynamicConfigEvent event) { // Parse yaml file into map Optional<Map<String, Object>> convertOptional = converter.convert(event.getContent(), Map.class); if (convertOptional.isPresent()) { //Modify switch status CONFIG_MAP.put(ENABLE_KEY, (boolean) convertOptional.get().get(ENABLE_KEY)); } System.out.println("The plug-in configuration item has changed, the configuration item value is: " + event.getContent()); } }); }
To use dynamic configuration, you need to turn on the dynamic configuration service switch and modify the config.properties file in the config directory:
# Dynamically configure service switches agent.service.dynamic.config.enable=true
3.3.2 Dynamic Configuration Demonstration
To enable the dynamic configuration service, you need to start zookeeper locally. Start the host application and mount the Sermant Agent, and initiate a call to the host application interface service:
curl http://127.0.0.1:8080/sayHello?name=lihua
At this time, the switch is turned on by default, and the console output is as follows:
The time when the method execution started has been recorded hello lihua Method takes: 23 milliseconds
Start delivering dynamic configuration, create the /sermant/template-plugin/template-config node, and set the value of the node to “enable: false”:
create /sermant create /sermant/template-plugin create /sermant/template-plugin/template-config enable: false
The host application console prints the following output:
The plug-in configuration item has changed, the configuration item value is: enable: false
Make another call to the host application interface service:
curl http://127.0.0.1:8080/sayHello?name=lihua
You can see that the console prints out the content that the enhanced logic is not executed, indicating that the dynamic configuration is successfully delivered:
Do not execute enhancement logic hello lihua Enhancement logic is not executed
The demonstration of dynamic configuration ends here. For more details of dynamic configuration, please refer to the dynamic configuration function document of Sermant official website.
IV. Summary of this chapter
This article introduces the process of quickly developing service governance plug-ins based on the Sermant framework and how to use the Sermant Agent product. It can be found that through the capabilities provided by the Sermant underlying framework, we can easily develop plug-ins that meet our own needs. At the same time, combined with Sermant’s logging system, dynamic configuration and Backend components, we can enhance the functions of the service management plug-in in a more refined and flexible manner. Sermant is an agentless service grid based on Java bytecode enhancement technology. It is non-intrusive, plug-inable and high-performance. I hope this article will be helpful to developers who are willing to use Sermant products!
As a bytecode enhancement framework focusing on the field of service governance, Sermant is committed to providing a high-performance, scalable, easy-to-access, and feature-rich service governance experience, and will take care of performance, functionality, and experience in each version. , everyone is widely welcome to join.
- Sermant Official website: https://sermant.io
- GitHub Warehouse address: https://github.com/huaweicloud/Sermant
- Scan the QR code to join the Sermant community communication group
The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Cloud native entry-level skills treeHomepageOverview 17033 people are learning the system