跳至主要内容

Microservice Log Practice(1): Log Log

Microservice Log Practice(1): Log Log

The project tony worked on is now in a painful change: from the old monolithic application to new style microservice model. The leader gives him a job to do the new logging system, from logging the log, log collection, to log analyzing.

Log in Monolithic Applications

“We attach great importance to the logging system, do you understand why?” Leader asked.

“Yep, the log can be used to debug the application in production environment in which we can’t set breakpoints. It can also be used to monitor the application status about the its health. We can even do the intrusion detection and related security by log.” Tony answered.

"Yes, you are right. In a monolithic application, we package all functionality into a single Jar/War, then deploy it using application server like Tomcat or even Glassfish. It has some disadvantages like bad scalability, small changes leading to whole application re-deployment etc. But it also some convenience in logging:

  • The configuration is centralized – log configuration is centralized in those Jar;
  • The logging result is centralized – logging result is in somewhere of server;
  • The log is naturally grouped by request;

“So, in our new microservice application, we still need those functionality.” Leader said.

“Em, the first two requirement is easy to understand. What’s meaning of the third one?”

“Saying we have a user request into the monolithic application, the log content in the invocation chain is grouped by their invocation order. We can easily tell how the request is processed if we have fine-tuned log. But in microservice, the log is decentralized in different services. We need use the new logging system to group them together.” Leader added.

“Ok, I understand.”

Log with Spring Cloud

“Considering our team using the Spring Cloud as the microservice framework, we need to see how to centralize logging config in Spring.” Tony said to himself.

After some searching, tony found the Spring Cloud Config module.

"First, we need to add dependency to setup Spring Cloud Config server:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
    <version>1.1.2.RELEASE</version>
</dependency>

"Then, we EnableConfigServer using annotation:

@SpringBootApplication
@EnableConfigServer
public class ConfigServer {  
    public static void main(String[] arguments) {
        SpringApplication.run(ConfigServer.class, arguments);
    }
}

"Next, we can config the where are our config file stores. In our case, we use git-based repo:

server.port=8888
spring.cloud.config.server.git.uri=ssh://localhost/config-repo
spring.cloud.config.server.git.clone-on-start=true

"And If we have a client with proper dependency spring-cloud-starter-config and config files are positioned according to the following rule, config server will return the config files according to url:

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

where “application” is the spring.config.name in the SpringApplication, “profile” is an active profile (or comma-separated list of profiles), “label” is an optional git branch label (defaults to “master”.)" Tony thought when writing the demo.

Share Common Spring Config

“In above method, we store different applications’ config in different files. How to share common configs across all of the applications?” Tony wonder

After some google, tony find that application.[properties|yml] is shared across all applications using config server. So adding the common config in application.[properties|yml] is done.

Share Plain Text Config

"But in our case, we want to share logback config because we use some logback specific config which can’t be configurated in application.yml but in logback.xml. How to achieve it? Just adding logback.xml in root folder seems doesn’t work1.

“It seems that there exists no other way. I can only do the following workaround in shared application.yml. When Spring Boot download the shared config from config server, it can then retrieve log config by itself.” Tony thought.

logging:
    config: http://host:port/path/logback.xml

“Oh, it’s too late. I just finish the first requirement of config centralization. I need to do others tomorrow.” Tony notice the time then go to the bed.

Ref

Written with StackEdit.


  1. According to the official document of Spring Cloud Config, it should work. But as far as we have tried, it doesn’t work :(. ↩︎

评论

此博客中的热门博文

Spring Boot: Customize Environment

Spring Boot: Customize Environment Environment variable is a very commonly used feature in daily programming: used in init script used in startup configuration used by logging etc In Spring Boot, all environment variables are a part of properties in Spring context and managed by Environment abstraction. Because Spring Boot can handle the parse of configuration files, when we want to implement a project which uses yml file as a separate config file, we choose the Spring Boot. The following is the problems we met when we implementing the parse of yml file and it is recorded for future reader. Bind to Class Property values can be injected directly into your beans using the @Value annotation, accessed via Spring’s Environment abstraction or bound to structured objects via @ConfigurationProperties. As the document says, there exists three ways to access properties in *.properties or *.yml : @Value : access single value Environment : can access multi

Elasticsearch: Join and SubQuery

Elasticsearch: Join and SubQuery Tony was bothered by the recent change of search engine requirement: they want the functionality of SQL-like join in Elasticsearch! “They are crazy! How can they think like that. Didn’t they understand that Elasticsearch is kind-of NoSQL 1 in which every index should be independent and self-contained? In this way, every index can work independently and scale as they like without considering other indexes, so the performance can boost. Following this design principle, Elasticsearch has little related supports.” Tony thought, after listening their requirements. Leader notice tony’s unwillingness and said, “Maybe it is hard to do, but the requirement is reasonable. We need to search person by his friends, didn’t we? What’s more, the harder to implement, the more you can learn from it, right?” Tony thought leader’s word does make sense so he set out to do the related implementations Application-Side Join “The first implementation

Implement isdigit

It is seems very easy to implement c library function isdigit , but for a library code, performance is very important. So we will try to implement it and make it faster. Function So, first we make it right. int isdigit ( char c) { return c >= '0' && c <= '9' ; } Improvements One – Macro When it comes to performance for c code, macro can always be tried. #define isdigit (c) c >= '0' && c <= '9' Two – Table Upper version use two comparison and one logical operation, but we can do better with more space: # define isdigit(c) table[c] This works and faster, but somewhat wasteful. We need only one bit to represent true or false, but we use a int. So what to do? There are many similar functions like isalpha(), isupper ... in c header file, so we can combine them into one int and get result by table[c]&SOME_BIT , which is what source do. Source code of ctype.h : # define _ISbit(bit) (1 << (