微服务架构师封神之路02-为你的微服务应用添加日志
微服务架构师封神之路02-为你的微服务应用添加日志
- 关于Kubernetes日志架构
- 我们的目标
- helloworld project
- 项目结构
- pom.xml
- Dockerfile
- AppMain.java
- log4j2.xml
- 部署测试
- 参考材料与延伸阅读
关于Kubernetes日志架构
讨论这个话题的技术文章不少,就是废话太多。简单说两个层面,
- 每个微服务内部:将日志写入到标准输出流中(Standard output stream, stdout and stderr)
- 整个Kubernetes cluster:在每个node上部署logging agent (运行在pod上的应用),将微服务写入stdout和stderr的日志转发到另外一个集中的地方存储。实现集中监控管理。
以上是一种最简单的日志架构设计,在实际操作中根据具体的情况还可能会有各种的变异。比如,微服务中的日志已经以文件形式存在,logging agent可能要先将file转化为stdout,再做转发操作。但核心思想是一样的,把分布在各处的日志集中到一个地方实现集中管理和监控。
我们的目标
为我们的微服务添加日志就包含了两个层面的工作,
- 为微服务项目添加具体的java日志工具,并将输出到stdout
- 在kubernetes node上安装logging agent,和转发后的data storage
紧接着就涉及了技术选型的问题, - 第一个问题我选择log4j2。原因也不多说了,目前log4j2优势明显,异步试日志的效率更是一骑绝尘,竟然可以达到其它工具的十倍效率以上。
- 第二个问题我选择Elasticsearch+Kibana。在Kubernetes文档上还有另一个选择是Stackdriver logging,看起来是在Google cloud platform上才能用,没有Elasticsearch+Kibana那么通用。
***今天我只能完成第一个目标,为helloworld项目添加日志工具,并输出到stdout。***第二个目标留着下次完成,我还要需要的文档再实践。
helloworld project
项目结构
文件列表:
- pom.xml
- Dockerfile
- AppMain.java
- log4j2.xml
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.4.RELEASE</version></parent><groupId>com.b5wang.cloudlab</groupId><artifactId>helloworld</artifactId><version>1.1-SNAPSHOT</version><packaging>jar</packaging><name>helloworld</name><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><!-- dependencies' version --><spring-boot-dependencies.version>2.3.0.RELEASE</spring-boot-dependencies.version></properties><build><finalName>${project.artifactId}</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!-- =========================================================================== Copy docker config files into target/docker-build folder =========================================================================== --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>3.1.0</version><executions><execution><id>generate-docker-build</id><phase>generate-resources</phase><goals><goal>copy-resources</goal></goals><configuration><outputDirectory>${project.build.directory}/docker-build</outputDirectory><resources><resource><directory>${project.basedir}/src/docker</directory><filtering>true</filtering></resource></resources></configuration></execution></executions></plugin><!-- =========================================================================== Create docker image =========================================================================== --><plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>1.6.0</version><executions><execution><id>exec-docker-build</id><phase>package</phase><goals><goal>exec</goal></goals><configuration><executable>docker</executable><commandlineArgs>build --no-cache --tag b5wang/helloworld:1.1 -f ${project.build.directory}/docker-build/Dockerfile ${project.build.directory}</commandlineArgs></configuration></execution></executions></plugin><!-- fix error java.lang.ClassNotFoundException: org.apache.maven.doxia.siterenderer.DocumentContent --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-site-plugin</artifactId><version>3.8.2</version></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-project-info-reports-plugin</artifactId><version>3.0.0</version></plugin></plugins></build><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot-dependencies.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency></dependencies>
</project>
Dockerfile
FROM openjdk:8-jdk-alpine
COPY helloworld.jar /app/helloworld.jar
ENTRYPOINT ["java","-jar","/app/helloworld.jar"]
AppMain.java
package com.b5wang.cloudlab.helloworld;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@EnableAutoConfiguration
public class AppMain {private static final Logger LOGGER = LogManager.getLogger(AppMain.class);@RequestMapping("/")String home() {LOGGER.trace("helloworld is called?!");LOGGER.debug("helloworld is called?!");LOGGER.info("helloworld is called?!");LOGGER.error("helloworld is called?!");LOGGER.fatal("helloworld is called?!");return "minikube: Hello World!";}public static void main(String[] args) throws Exception {LOGGER.info("helloworld app is starting......");// Log will not be printed out before spring app start.SpringApplication.run(AppMain.class, args);LOGGER.trace("helloworld app has started?!");LOGGER.debug("helloworld app has started?!");LOGGER.info("helloworld app has started?!");LOGGER.error("helloworld app has started?!");LOGGER.fatal("helloworld app has started?!");}
}
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN"><Appenders><Console name="STDOUT" target="SYSTEM_OUT"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></Console></Appenders><Loggers><Logger name="com.b5wang.cloudlab.helloworld" level="debug" /><Root level="error"><AppenderRef ref="STDOUT"/></Root></Loggers>
</Configuration>
部署测试
具体过程如果需要参考请见:微服务架构师封神之路01-利用minikube部署一个最简单的应用
查看pod日志的几种方式:
- Minikube UI: $ minikube dashboard
- kubectl logs -f helloworld
- docker service logs
今天就到这里!
下次我们讨论如何将微服务应用和cloud platform同意起来,形成一个完整的日志架构。谢谢,再见! :)
参考材料与延伸阅读
Kubernetes logging architecture: https://kubernetes.io/docs/concepts/cluster-administration/logging/
kubectl log command - https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#logs
Docker logging: https://docs.docker.com/config/containers/logging/configure/
Log4j2 logging in the cloud: https://logging.apache.org/log4j/2.x/manual/cloud.html
Logs: https://12factor.net/logs
微服务架构师封神之路02-为你的微服务应用添加日志相关推荐
- 微服务架构师封神之路09-Springboot多数据源,Hikari连接池和事务配置
微服务架构师封神之路09-Springboot多数据源,Hikari连接池,和事务的配置 application.yml 初始化DataSource DataSourceConfig的两种写法 写法一 ...
- 硬核干货:一位码农的架构师封神之路!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 转自机器之心 几天前,高级架构师 Justin Miller 在 ...
- GitHub热门:程序员的架构师封神之路
GitHub 趋势榜第一的项目来自架构师 Justin Miller,他分享了自己关于「如何成为更好的软件架构师」的想法,这个 repo 现在已有 5.4k star. 几年前有人问我:「你是怎么成为 ...
- 阿里云王牌架构师一问开发者:系统要改造成微服务吗
阿里云高级解决方案架构师 杨旭 世界最大混合云的总架构师,4年前,开始作为双11阿里云技术负责人,负责搭建全球最大的混合云结构,把 "双11"的电商业务和技术场景在阿里云上实现,并 ...
- “自由主义教皇” 、Linux 之父的封神之路
作者 | 年素清 责编 | 王晓曼 出品 | 程序人生(ID:coder_life) "有些人生来就具有统率百万人的领袖风范:另一些人则是为写出颠覆世界的软件而生.唯一一个能同时做到这两者的 ...
- GitHub 的“封神”之路!
2008年,在无数人为代码协作方式而感到异常头疼的时候,GitHub 横空出世,完美契合了市场的迫切需求.自此,它以惊人的速度成长起来并蔓延到全世界,彻底融入开发编程的日常之中.仅仅十年,现在的 Gi ...
- python猜数字1001untitled_pytest封神之路第零步 快速入门
背景:本文是在系列第五篇发表后的补充篇章,第一篇介绍了tep,可能对不熟悉pytest的朋友不够友好,特意补充入门篇,帮大家快速了解如何动手写pytest.如果你是从这篇文章第一次阅读,那么请忽略以上 ...
- [架构之路-4]:架构师 - 架构师的四大架构价值等级与架构师全面成长之路
目录 第1章 架构师的四大架构价值等级 第一等级L1: 一知半解型(入门架构师)-- 辅助价值 第二等级L2: 拆解还原型(初级架构师)-- 表层价值.协调价值 第三等级L3: 革新型(中级架构师)- ...
- 华为硬件工程师手册_华为认证云服务架构师正式发布
华为认证HCIP-Cloud Service Solutions Architect V2.0(中文版)自2020年1月20日起,正式全球发布. 发布概述 基于"平台+生态"战略, ...
最新文章
- setuid和setgid
- 一对一直播app源码功能操详解方案分享
- 主席树 + 树上倍增 ---- codeforces 587C[树上倍增或者主席树]
- OssImport系列之四——最佳实践
- ajax 载入html后不能执行其中的js解决方法
- idea(三)最值得安装的几款插件
- [转载]高质量c/c++编程指南读书笔记
- 坑爹的uint32_t
- 深入理解Angular订阅者模式
- duration java_Java Duration类| 带示例的getUnits()方法
- typeof 数据类型转换
- kcp-go源码解析
- 【Elasticsearch】解除索引只读限制 read-only
- Java 实现享元(Flyweight)模式
- PHP 实现 阿里云 短信接口调用
- 希腊字母表 ← LaTeX
- pla3d打印材料密度_最新研究:PLA在3D打印中产生的有害气体最少
- 惠不停返利网:掀起购物返利高潮
- HDD硬盘在数据中心的持续价值
- 资深摄影师眼中 青岛值得一游的景点有哪些之4
热门文章
- BottomSheetDialogFragment仿制抖音评论框
- jsf1.2/facelet1.x 中convertor的自定义
- 电脑音频图标出现小红×无法播放声音、Windows Audio拒绝访问0x80070005的解决办法
- 赤峰学院计算机等级考试,教学研究
- 浙江嵊州根雕传承路:政府艺人联心 演绎“小城大艺”
- keyshot怎么贴logo_KeyShot中Poliigon贴图的使用方法整理
- java类中数据成员
- 美国运营商进行5G网络测试:速度峰值可达10Gbps
- 爷青回|用Python制作【谷歌恐龙游戏】当你离线没网的时候,这将成为一种乐趣~
- 流水线三维可视化运维,装配自动化提质增效