微服务中的日志管理 — ELK

微服务中的日志管理 — ELK通过使用微服务,我们能够解决许多在单体应用中暴露的问题,并且它允许我们创建稳定的分布式应用程序,并对代码,团队规模,维护,发布周期,云计算等进行所需要的控制。但同时微服务也引入了一些挑战,例如分布式日志管理和查看。需要提供在众多服务中查看分布的完整事务日志和分布式调试的能力。实际上,挑战在于微服务是相互隔离的,它们不共享公共数据库和日志文件。随着微服务数量的增加以及我们使用自动化持续集成工具实现…

大家好,又见面了,我是你们的朋友全栈君。

通过使用微服务,我们能够解决许多在单体应用中暴露的问题,并且它允许我们创建稳定的分布式应用程序,并对代码,团队规模,维护,发布周期,云计算等进行所需要的控制。但同时微服务也引入了一些挑战,例如分布式日志管理和查看。需要提供在众多服务中查看分布的完整事务日志和分布式调试的能力。

实际上,挑战在于微服务是相互隔离的,它们不共享公共数据库和日志文件。随着微服务数量的增加以及我们使用自动化持续集成工具实现云部署,当我们遇到任何问题时,非常有必要对组件进行调试。

幸运的我们已经拥有了一系列工具,可将它们一起使用发挥魔力。一组流行的工具是Elastic Search,Logstash和Kibana —— 放在一起被称为ELK堆栈。它们用于实时搜索,分析和可视化日志数据。

在本文中,介绍了如何将ELK堆栈集成到微服务生态系统中。

1. 什么是ELK

  • Elasticsearch是一种基于JSON的分布式搜索和分析引擎,提供水平可扩展性,为高可靠性和易管理性而设计。
  • Logstash是一个动态数据收集管道,具有可扩展的插件生态系统和强大的Elasticsearch协同作用。
  • Kibana通过 UI 提供数据可视化。

ELK 架构

Logstash根据我们设置的过滤条件处理应用程序日志文件,并将这些日志发送到Elasticsearch。通过Kibana,我们可以在需要时查看和分析这些日志。

ELK操作方式

2. ELK安装

所有这三个工具都基于JVM,在开始安装之前,请验证JDK是否已正确配置。检查标准JDK 1.8安装,JAVA_HOME并且PATH已经完成设置。

2.1 Elasticsearch

  • 从此下载页面下载最新版本的Elasticsearch 并将其解压缩到任何文件夹中。
  • 在命令提示符下运行bin\elasticsearch.bat。
  • 默认情况下,它可从http://localhost:9200开始访问

2.2 Kibana

  • 下载页面下载最新的发行版并解压缩到任何文件夹中。
  • 在编辑器中打开config/kibana.yml,并设置elasticsearch.url指向您的Elasticsearch实例。在我们的例子中,elasticsearch.url: “http://localhost:9200
  • 在命令提示符下运行bin\kibana.bat。
  • 成功启动后,Kibana将启动默认端口5601,Kibana UI将通过http://localhost:5601访问

2.3 Logstash

  • 下载页面下载最新的发行版并解压缩到任何文件夹中。
  • 根据配置说明创建一个文件logstash.conf。我们将在后面实际演示时再次确定配置。
  • 现在运行bin/logstash -f logstash.conf以启动logstash。

3. 创建微服务

3.1 创建Spring Boot项目

让我们使用spring boot创建一个应用程序。MAVEN依赖如下:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.5.6.RELEASE</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
	<java.version>1.8</java.version>
</properties>

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-rest</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

3.2 添加REST端点

新建一个RestController类来暴露一些端点/elk,/elkdemo,/exception。实际上我们只是输出了几个日志语句,因此可以根据您的选择随意添加/修改日志。

@RestController
public class ELKController {
	private static final Logger LOG = Logger.getLogger(ELKController.class.getName());
	
	@Autowired
	RestTemplate restTemplete;
	
	@Bean
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
	
	@RequestMapping(value = "/elkdemo")
	public String helloWorld() {
		String response = "Hello user ! " + new Date();
		LOG.log(Level.INFO, "/elkdemo - > " + response);

		return response;
	}
	
	@RequestMapping(value = "/exception")
	public String exception() {
		String rsp = "";
		try {
			int i = 1 / 0;
			// should get exception
		} catch (Exception e) {
			e.printStackTrace();
			LOG.error(e);
			
			StringWriter sw = new StringWriter();
			PrintWriter pw = new PrintWriter(sw);
			e.printStackTrace(pw);
			String sStackTrace = sw.toString(); // stack trace as a string
			LOG.error("Exception As String :: - > "+sStackTrace);
			
			rsp = sStackTrace;
		}

		return rsp;
	}
	
	@RequestMapping(value = "/elk")
	public String helloWorld1() {

		String response = restTemplete.exchange("http://localhost:8080/elkdemo", HttpMethod.GET, null, new ParameterizedTypeReference<String>() {
		}).getBody();
		LOG.log(Level.INFO, "/elk - > " + response);

		try {
			String exceptionrsp = restTemplete.exchange("http://localhost:8080/exception", HttpMethod.GET, null, new ParameterizedTypeReference<String>() {
			}).getBody();
			LOG.log(Level.INFO, "/elk trying to print exception - > " + exceptionrsp);
			response = response + " === " + exceptionrsp;
		} catch (Exception e) {
			// exception should not reach here. Really bad practice :)
		}

		return response;
	}
}

3.3 配置Spring boot Logging

logging.file=elk-example.log
spring.application.name = elk-example

3.4 验证微服务生成的日志

构建并启动应用程序,通过浏览器访问http://localhost:8080/elk。会看到一些异常信息输出。

转到应用程序根目录并检查是否已创建日志文件elk-example.log,并对端点执行几次访问并验证日志文件中是否添加了日志。

4. Logstash配置

我们需要创建一个logstash配置文件,以便让它监听日志文件并将日志消息推送到Elasticsearch。以下是示例中介绍了logstash 配置,请根据你的设置更改日志路径。

input {
  file {
    type => "java"
    path => "D:/eclipse-workspace/java-samples/elk-example-spring-boot/elk-example.log"
    codec => multiline {
      pattern => "^%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{TIME}.*"
      negate => "true"
      what => "previous"
    }
  }
}
 
filter {
  #If log line contains tab character followed by 'at' then we will tag that entry as stacktrace
  if [message] =~ "\tat" {
    grok {
      match => ["message", "^(\tat)"]
      add_tag => ["stacktrace"]
    }
  }
 
 grok {
    match => [ "message",
               "(?<timestamp>%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{TIME})  %{LOGLEVEL:level} %{NUMBER:pid} --- \[(?<thread>[A-Za-z0-9-]+)\] [A-Za-z0-9.]*\.(?<class>[A-Za-z0-9#_]+)\s*:\s+(?<logmessage>.*)",
               "message",
               "(?<timestamp>%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{TIME})  %{LOGLEVEL:level} %{NUMBER:pid} --- .+? :\s+(?<logmessage>.*)"
             ]
  }
 
  
  date {
    match => [ "timestamp" , "yyyy-MM-dd HH:mm:ss.SSS" ]
  }
}
 
output {
   
  stdout {
    codec => rubydebug
  }
 
  # Sending properly parsed log events to elasticsearch
  elasticsearch {
    hosts => ["localhost:9200"]
  }
}

5. Kibana配置

在查看Kibana中的日志之前,我们需要配置索引模式。我们可以配置logstash-*为默认配置。

在Kibana中,打开“Management”,然后单击“Index Patterns”。如果这是你的第一个索引模式,则会自动打开“Create index pattern”页面。 否则,单击左上角的“Create index pattern”。在索引模式Index pattern 字段中输入logstash-*。

创建索引模式

单击下一步Next step。在配置设置Configure settings中,在时间过滤器字段名称Time Filter field name下拉菜单中选择@timestamp。

时间过滤器

注意:
定义索引模式时,与该模式匹配的索引必须存在于Elasticsearch中,并且它们必须包含数据。 要检查哪些索引可用,
可使用curl -XGET “http://localhost:9200/_cat/indices?v”。

索引模式管理页面如下所示。通过这种配置,我们将Kibana指向你选择的Elasticsearch索引。Logstash使用名称模式创建索引,名称格式为logstash-YYYY.MM.DD

索引模式管理

6.验证

现在,当所有组件都启动并运行时,让我们验证整个生态系统。

转到应用程序并访问端点几次以便生成日志,然后转到Kibana控制台,看看日志是否正确堆叠在Kibana中,还有许多额外的功能,比如我们可以过滤,查看内置的不同图表等。

以下是Kibana中生成的日志的视图。

Kibana视图

7. 总结

在这个ELK示例中,我们学习了如何配置ELK堆栈以及如何将应用程序日志文件指向ELK,并查看和分析Kibana中的日志。除了演示的这些功能外还可以有很多其他的配置。例如:

  • 不是监听我们的日志文件,我们可以通过logback配置来使用TCP appender,通过TCP协议将日志发送到远程Logstash实例。
  • 我们可以使用Logstash指向多个日志文件。
  • 我们可以在logstash配置文件中使用更复杂的过滤器,以根据需要执行更多操作。
  • 我们可以使用远程ELK集群指向我们的日志文件,或者将日志推入,这在将应用程序部署到云中时是必需的。
  • 在logstash中创建不同的索引模式。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/134700.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Java volatile的性能分析「建议收藏」

    Java volatile的性能分析「建议收藏」volatile通过内存屏障来实现禁止重排序,通过Lock执行来实现线程可见性,如果我们的程序中需要让其他线程及时的对我们的更改可见可以使用volatile关键字来修饰,比如AQS中的state所以在一个线程写,多个线程读的情况下,或者是对volatile修饰的变量进行原子操作时,是可以实现共享变量的同步的,但是i++不行,因为i++又三个操作组成,先读出值,然后再对值进行+1,接着讲结果写入,这个过程,如果中间有其他线程对该变量进行了修改,那么这个值就无法得到正确的结果。今天我们讨论的重

    2022年7月18日
    17
  • log4j pattern详解_pid参数的物理意义

    log4j pattern详解_pid参数的物理意义1、常用标志:-X:X信息输出时左对齐 %p:输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL, %d:输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy-MM-ddHH:mm:ss,SSS},输出类似:2011-10-1822:10:28,921 %r:输出自应用启动到输出该log信

    2022年8月22日
    16
  • 锚点平滑滚动之scrollIntoView

    锚点平滑滚动之scrollIntoView<!DOCTYPEhtml><htmllang=”en”><head><metacharset=”UTF-8″><title>锚点平滑滚动</title><style>#d1{background-color:#FFFCF0;height:400px;}#d2{.

    2022年6月18日
    20
  • 计算机电脑怎么改皮肤,终极:如何更改计算机鼠标的皮肤「建议收藏」

    如何更改计算机鼠标的皮肤图33.点击左侧菜单栏中的“鼠标”,进入鼠标设置页面如何更改计算机鼠标的皮肤图44.在鼠标设置页面中找到“其他鼠标选项”的蓝线,单击以输入,在弹出窗口中单击“指针”,然后单击“解决方案”以查看下图<如何更改计算机鼠标的皮肤图55.这是Windows的默认鼠标指针页面,但是许多朋友会看到他们朋友的计算机鼠标指针具有其他新颖的样式,并且不包含在Windows的默认指…

    2022年4月12日
    56
  • ORACLE索引,索引的建立、修改、删除[通俗易懂]

    ORACLE索引,索引的建立、修改、删除[通俗易懂]一、简介      索引是关系数据库中用于存放每一条记录的一种对象,主要目的是加快数据的读取速度和完整性检查。建立索引是一项技术性要求高的工作。一般在数据库设计阶段的与数据库结构一道考虑。应用系统的性能直接与索引的合理直接有关二、语法2.1创建索引CREATEINDEXCREATE[unique]INDEX[user.]indexON[user.]table(column[AS

    2025年9月12日
    7
  • bzero memset_memset是什么函数

    bzero memset_memset是什么函数 bzero函数函数原型:voidbzero(void*s,intn);头文件:#include&lt;string.h&gt;功能:将字符串s的前n个字节置为0,一般来说n通常取sizeof(s),将整块空间清零。返回值:无返回值例子:将一个数组清零:charstr[10];bzero(str,…

    2022年10月13日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号