分布式应用监控

分布式应用监控

image
分布式系统已经诞生了很长时间,现代互联网公司规模都变得异常庞大,系统也变得越来越复杂,给监控工作带来了极大的难度:海量日志数据如何处理,服务如何追踪,如何高效定位故障缩短故障时常,常见的监控手段可以分为集中式日志系统(Logging),集中式度量系统(Metrics)和分布式追踪系统(Tracing)。

集中式日志系统

集中式日志系统,选取了最具代表性的ELK
image

Elasticsearch

Elasticsearch是个开源的分布式搜索引擎,提供搜索、分析、存储数据三大功能。它的特点有:分布式、自动发现、索引自动分片、索引副本机制、RESTful 风格接口、多数据源以及自动搜索负载等。
image

Logstash

Logstash 是一个开源的动态数据收集处理管道,它可以同时从多个源中提取数据,对其进行转换,并且拥有可扩展的插件生态系统,能够与 Elasticsearch 产生强大的协同作用。
image

Kibana

Kibana是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的。你可以用kibana搜索、查看存放在Elasticsearch中的数据。Kibana与Elasticsearch的交互方式是各种不同的图表、表格、地图等,直观的展示数据,从而达到高级的数据分析与可视化的目的。
image

Beats

Beats 是 ELK Stack 技术栈中负责单一用途数据采集并推送给 Logstash 或 Elasticsearch 的轻量级产品。包括:

  • Filebeats:应用于日志收集场景的实现。
  • Metricbeat:轻量级的系统级性能指标监控工具。
  • Packetbeat:轻量级的网络数据包分析工具。
  • Winlogbeat:轻量级的 Windows 事件日志收集工具。
  • Heartbeat:心跳检测工具,主要监控服务的可用性。

image

安装

修改虚拟机的内存限制

1
vi /etc/sysctl.conf

加入

1
vm.max_map_count=262144

sysctl -p查看设置

docker安装ELK

1
2
docker pull sebp/elk
docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -e ES_MIN_MEM=128m -e ES_MAX_MEM=1024m -it --name elk sebp/elk

输入网址http://<your-host>:5601可以看到下面的界面,则说明安装成功
image

配置使用

1
docker exec -it <container-name> /bin/bash

进入容器,执行命令

1
/opt/logstash/bin/logstash -e 'input { stdin { } } output { elasticsearch { hosts => ["localhost"] } }'

如果有错误信息

1
service logstash stop

当命令成功被执行后,看到:Successfully started Logstash API endpoint {:port=>9600}信息后,输入:this is a dummy entry然后回车,模拟一条日志进行测试。

打开浏览器http://<your-host>:9200/_search?pretty,如图所示
image

打开浏览器,输入:http://<your-host>:5601 点击创建
image

看到如下界面,到此安装结束。
image

与java应用结合的日志分析系统可以通过Beats的Filebeats来实现,通过log4j将运行日志输出在文件中,通过Filebeats插件利用Logstash过滤并导入到Elasticsearch中,最后通过Kibana展示。

集中式度量系统

Prometheus

Prometheus是一个基于时间序列的数值数据的监控解决方案,这是一个开源项目,由前Google员工在SoundCloud启动,他们希望监控一个高度动态的容器环境,因为对传统的监控工具不甚满意,所以开发出Prometheus,并在上面进行工作。Prometheus解决了Devs如何监控高动态容器环境的问题。

例如我们想要获取所有的服务器上node_exporter暴露出来的数据,就必须有个程序去定时访问这些接口,如果想要增加或者修改这些接口,那么就需要有个配置文件来记录这些服务器的地址,如果想要访问历史的某个时间点的数据,那么就必须按照时间顺序存储获取到的指标和值。而如果想要将值绘制成图,也需要有代码去查询、计算和渲染。最后你可能还希望当服务器的某个指标超过一定的阈值时,向指定的接口发出告警信息。一切的一切其实都可以使用Prometheus来解决。

image

Prometheus检测mysql相关指标

前提:本地安装了mysql

安装node-exporter

1
2
docker pull node-exporter
docker run -d -p 9100:9100 --cap-add SYS_TIME --net="host" --pid="host" -v "/:/host:ro,rslave"quay.io/prometheus/node-exporter --cap-add=SYS_TIME --path.rootfs /host

安装mysqld-exporter

通过mysql命令界面创建相应角色并赋予权限

1
2
CREATE USER 'mysql_monitor'@'localhost' IDENTIFIED BY 'XXXXXXXX' WITH MAX_USER_CONNECTIONS 3;
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'mysql_monitor'@'localhost';

docker安装

1
2
docker pull mysqld-exporter
docker run -d -p 9104:9104 -e DATA_SOURCE_NAME="mysql_monitor:root@(127.0.0.1:3306)/" prom/mysqld-exporter

安装Prometheus

创建文件prometheus.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
global:
scrape_interval: 60s
evaluation_interval: 60s

scrape_configs:
- job_name: prometheus
static_configs:
- targets: ['106.15.226.184:9090']
labels:
instance: prometheus

- job_name: linux
static_configs:
- targets: ['106.15.226.184:9100']
labels:
instance: db1

- job_name: mysql
static_configs:
- targets: ['106.15.226.184:9104']
labels:
instance: db1

docker启动

1
2
docker pull prometheus
sudo docker run -d -p 9090:9090 -v /root/conf/prometheus.yml:/usr/local/src/file/prometheus.yml quay.io/prometheus/prometheus --config.file=/usr/local/src/file/prometheus.yml

安装Grafana

1
2
docker pull grafana/grafana
docker run -d --name=grafana -p 3000:3000 grafana/grafana

打开http:x.x.x.x:9090
image
如图所示,说明数据源管道agent启动成功

打开http://x.x.x.x:3000,配置Prometheus数据源
image

配置好数据源后,下载mysql监控模板
解压后,找到mysql开头的模板,导入,最后如图所示:
image

image

Cat

image
CAT(Central Application Tracking)是一个实时和接近全量的监控系统,它侧重于对Java应用的监控,基本接入了美团上海侧所有核心应用。目前在中间件(MVC、RPC、数据库、缓存等)框架中得到广泛应用,为美团各业务线提供系统的性能指标、健康状况、监控告警等。

image

监控整体要求就是快速发现故障、快速定位故障以及辅助进行程序性能优化。为了做到这些,我们对监控系统的一些非功能做了如下的要求:

实时处理:信息的价值会随时间锐减,尤其是事故处理过程中。
全量数据:最开始的设计目标就是全量采集,全量的好处有很多。
高可用:所有应用都倒下了,需要监控还站着,并告诉工程师发生了什么,做到故障还原和问题定位。
故障容忍:CAT本身故障不应该影响业务正常运转,CAT挂了,应用不该受影响,只是监控能力暂时减弱。
高吞吐:要想还原真相,需要全方位地监控和度量,必须要有超强的处理吞吐能力。
可扩展:支持分布式、跨IDC部署,横向扩展的监控系统。
不保证可靠:允许消息丢失,这是一个很重要的trade-off,目前CAT服务端可以做到4个9的可靠性,可靠系统和不可靠性系统的设计差别非常大。
CAT从开发至今,一直秉承着简单的架构就是最好的架构原则,主要分为三个模块:CAT-client、CAT-consumer、CAT-home。

Cat-client 提供给业务以及中间层埋点的底层SDK。
Cat-consumer 用于实时分析从客户端提供的数据。
Cat-home 作为用户给用户提供展示的控制端。
在实际开发和部署中,Cat-consumer和Cat-home是部署在一个JVM内部,每个CAT服务端都可以作为consumer也可以作为home,这样既能减少整个层级结构,也可以增加系统稳定性。
上图是CAT目前多机房的整体结构图,图中可见:

路由中心是根据应用所在机房信息来决定客户端上报的CAT服务端地址,目前美团有广州、北京、上海三地机房。
每个机房内部都有独立的原始信息存储集群HDFS。
CAT-home可以部署在一个机房也可以部署在多个机房,在最后做展示的时候,home会从consumer中进行跨机房的调用,将所有的数据合并展示给用户。
实际过程中,consumer、home以及路由中心都是部署在一起的,每个服务端节点都可以充当任何一个角色。

安装使用Cat

本文演示单机集群安装部署

1
2
3
git clone https://github.com/dianping/cat.git
cd docker
docker-compose up

第一次运行以后,数据库中没有表结构,需要通过下面的命令创建表:

1
docker exec <container_id> bash -c "mysql -uroot -Dcat < /init.sql"

依赖配置说明

  • datasources.xml
    • CAT数据库配置,默认配置是mysql镜像,可以按需替换
  • docker-compose.yml
    • 通过docker-compose启动的编排文件,文件中包含cat和mysql。可以屏蔽掉mysql的部分,并且修改cat的环境变量,改为真实的mysql连接信息。
  • client.xml
    • CAT 初始化默认的路由列表,配置此文件可以将客户端数据上报指向到不同环境。
  • datasources.sh
    • 辅助脚本,脚本作用时修改datasources.xml,使用环境变量中制定的mysql连接信息。(通过sed命令替换)

Java 应用的集成

参考博客
需要指定 cat 专用的远程仓库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- %MAVEN_HOME%\conf\settings.xml -->

<profiles>
<profile>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>central</id>
<layout>default</layout>
<url>http://repo1.maven.org/maven2</url>
</repository>
<repository>
<id>unidal.nexus</id>
<url>http://unidal.org/nexus/content/repositories/releases/</url>
</repository>
</repositories>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</profile>
</profiles>

加入依赖(pom.xml)

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>com.dianping.cat</groupId>
<artifactId>cat-client</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>

添加过滤器 CatFilter

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class CatFilterConfigure {
@Bean
public FilterRegistrationBean catFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new CatFilter());
registration.addUrlPatterns("/*");
registration.setName("cat-filter");
registration.setOrder(1);
return registration;
}
}

添加注解

1
2
3
4
5
6
7
8
9
10
@CatCacheTransaction
public void test() {
}

@ResponseBody
@RequestMapping("/hello")
@CatHttpRequestTransaction(type = "URL", name = "/hello")
public String hello() {
return "hello!";
}

image

更多集成
image

管理平台的使用

控制台
http://192.168.126.101:8080/cat
帐号/密码: catadmin/catadmin

项目配置
http://192.168.126.101:8080/cat/s/config?op=projects

相关文档
部署文档: http://192.168.126.101:8080/cat/r/home?op=view&docName=deploy
用户文档:http://192.168.126.101:8080/cat/r/home?op=view&docName=user
告警文档:http://192.168.126.101:8080/cat/r/home?op=view&docName=alert
集成文档:http://192.168.126.101:8080/cat/r/home?op=view&docName=integration
开发文档:http://192.168.126.101:8080/cat/r/home?op=view&docName=develop
设计文档:http://192.168.126.101:8080/cat/r/home?op=view&docName=design
常见问题:http://192.168.126.101:8080/cat/r/home?op=view&docName=problem

实时查看
http://192.168.126.101:8080/cat/r/t
image

分布式追踪系统

Zipkin

Zipkin是一种分布式跟踪系统。它有助于收集解决微服务架构中的延迟问题所需的时序数据。它管理这些数据的收集和查找。Zipkin的设计基于Google Dapper论文。
应用程序用于向Zipkin报告时序数据。Zipkin UI还提供了一个依赖关系图,显示了每个应用程序通过的跟踪请求数。如果要解决延迟问题或错误,可以根据应用程序,跟踪长度,注释或时间戳对所有跟踪进行筛选或排序。选择跟踪后,您可以看到每个跨度所需的总跟踪时间百分比,从而可以识别问题应用程序。
image

共有四个组件构成了 Zipkin:

  • collector
  • storage
  • search
  • web UI

Zipkin Collector

一旦追踪数据抵达 Zipkin Collector 守护进程,Zipkin Collector 为了查询,会对其进行校验、存储和索引。

Storage

Zipkin 最初是构建在将数据存储在 Cassandra 中,因为 Cassandra 易跨站,支持灵活的 schema,并且在 Twitter 内部被大规模使用。然而,我们将这个组件做成了可插拔式的。在 Cassandra 之外,我们原生支持 ElasticSearch 和 MySQL。可作为第三方扩展提供给其它后端。

Zipkin 查询服务

一旦数据被存储索引,我们就需要一种方式提取它。查询守护进程提供了一个简单的 JSON API 查询和获取追踪数据。API 的主要消费者就是 Web UI。

Web UI

我们创建了一个用户图形界面为追踪数据提供了一个漂亮的视图。Web UI 提供了基于服务、时间和标记(annotation)查看追中数据的方法。注意:UI 没有内置的身份认证功能。

image

安装部署

参考
前提条件:已经安装好ElasticSearch

安装zookeeper和kafka

1
2
3
docker pull wurstmeister/zookeeper  

docker pull wurstmeister/kafka

启动镜像

1
2
3
4
5
docker run -d --name zookeeper --publish 2181:2181 --volume /etc/localtime:/etc/localtime zookeeper:latest
docker run -d --name kafka --publish 9092:9092 --link zookeeper --env KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
--env KAFKA_ADVERTISED_HOST_NAME=kafka所在宿主机的IP --env KAFKA_ADVERTISED_PORT=9092 --volume /etc/localtime:/etc/localtime
wurstmeister/kafka:latest
docker run -d --name zipkin-server -p 9411:9411 -e "KAFKA_BOOTSTRAP_SERVERS=your-kafka-address" -e "STORAGE_TYPE=elasticsearch" -e "ES_HOSTS=your-es-host" -e "ES_INDEX=zipkin" -e "ES_INDEX_SHARDS=1" -e "ES_INDEX_REPLICAS=1" zipkin:latest

使用

用maven新建springboot项目
引入依赖,包括Spring Cloud Sleuth和Kafka传输的支持依赖Spring Stream Kafak以及web依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
</dependency>
</dependencies>

配置

1
2
3
4
5
6
7
8
9
10
spring:
application:
name: service-producer # 配置应用名称
kafka:
bootstrap-servers: localhost:9092 # 缓冲kafka地址
sleuth:
sampler:
percentage: 1 # 设置采样频率,默认为0.1,设置为全采样,便于观测,实际项目中根据具体情况设置
server:
port: 8080

类似的方法再新建一个项目然后写一个接口进行2个服务之间的通讯,触发调用链,可以在http://localhost:9411查看如下效果图:
image
image
image
需要注意的是,我们使用的存储模块是ES,所以一段时间内的服务调用关系图是无法直接得到的(使用内存存储可以直接得到)。我们需要使用Zipkin官方提供的zipkin-dependencies来生成依赖关系图。

1
2
# ex to run the job to process yesterday's traces on OS/X
$ STORAGE_TYPE=elasticsearch ES_HOSTS=your-es-host ES_INDEX=zipkin ES_NODES_WAN_ONLY=true java -jar zipkin-dependencies.jar `date -uv-1d +%F`

Pinpoint

Pinpoint是一个开源的APM监控工具,我们可以通过pinpoint实时跟踪应用之间的调用、程序的响应时间以及服务器资源使用状态,可以在分布式环境中为没个调用生成代码级别的可视图并定位瓶颈点和失败点。Pinpoint的设计也是基于Google Dapper论文
image

安装部署

参考

1
2
3
git clone https://github.com/naver/pinpoint-docker.git
cd Pinpoint-Docker
docker-compose pull && docker-compose up -d

如有问题,请修改相对路径为绝对路径

1
2
3
4
5
...
volumes:
- /home/pinpoint/hbase
- /home/pinpoint/zookeeper
...

启动镜像,访问http://x.x.x.x:8079/
image
hbase页面 http://x.x.x.x:16010/
image

Skywalking

Skywalking是一款优秀的国产 APM 工具,包括了分布式追踪、性能指标分析、应用和服务依赖分析等。通过在应用程序中添加 SkyWalking Agent,就可以将接口、服务、数据库、MQ等进行追踪,将追踪结果通过 HTTP 或 gRPC 发送到 SkyWalking Collecter,SkyWalking Collecter 经过分析和聚合,将结果存储到 Elasticsearch 或 H2,SkyWalking 同时提供了一个 SkyWalking UI 的可视化界面,UI 以 GraphQL + HTTP 方式获取存储数据进行展示。
image

安装部署

参考博客

使用

拷贝apache-skywalking-apm-incubating目录下的agent目录到应用程序位置,探针包含整个目录,请不要改变目录结构

java程序启动时,增加JVM启动参数,-javaagent:/path/to/agent/skywalking-agent.jar。参数值为skywalking-agent.jar的绝对路径

agent探针配置,简单修改下agent.application_code即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 当前的应用编码,最终会显示在webui上。
# 建议一个应用的多个实例,使用有相同的application_code。请使用英文
agent.application_code=Your_ApplicationName

# 每三秒采样的Trace数量
# 默认为负数,代表在保证不超过内存Buffer区的前提下,采集所有的Trace
# agent.sample_n_per_3_secs=-1

# 设置需要忽略的请求地址
# 默认配置如下
# agent.ignore_suffix=.jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg

# 探针调试开关,如果设置为true,探针会将所有操作字节码的类输出到/debugging目录下
# skywalking团队可能在调试,需要此文件
# agent.is_open_debugging_class = true

# 对应Collector的config/application.yml配置文件中 agent_server/jetty/port 配置内容
# 例如:
# 单节点配置:SERVERS="127.0.0.1:8080"
# 集群配置:SERVERS="10.2.45.126:8080,10.2.45.127:7600"
collector.servers=127.0.0.1:10800

# 日志文件名称前缀
logging.file_name=skywalking-agent.log

# 日志文件最大大小
# 如果超过此大小,则会生成新文件。
# 默认为300M
logging.max_file_size=314572800

# 日志级别,默认为DEBUG。
logging.level=DEBUG

一切正常的话,稍后就可以在skywalking ui看到了。
image

Jaeger

Uber开源的Jaeger用于监控和排除基于微服务的分布式系统,包括:

  • 分布式上下文传播
  • 分布式事务监控
  • 根本原因分析
  • 服务依赖性分析
  • 性能/延迟优化

image

安装部署

all-in-one 是Uber官方打包好的镜像,可以直接部署使用,但是只能用于测试环境,不能用于线上,因为它把数据放入了内存。

1
2
docker run -d -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p5775:5775/udp -p6831:6831/udp -p6832:6832/udp \
-p5778:5778 -p16686:16686 -p14268:14268 -p9411:9411 jaegertracing/all-in-one:latest

通过 http://localhost:16686 可以在浏览器查看 Jaeger的后台

正常安装参考

使用

参考

分布式链路追踪技术对比

来自博文

cat

由大众点评开源,基于Java开发的实时应用监控平台,包括实时应用监控,业务监控 。 集成方案是通过

代码埋点的方式来实现监控,比如: 拦截器,注解,过滤器等。 对代码的侵入性很大,集成成本较高。
支持技术栈:

  • dubbo
  • spring mvc ,spring aop ,springmvc-url
  • spring boot
  • mybatis
  • log4j , logback
  • playframework
  • http请求

风险较大。

zipkin

由Twitter团队开源, Zipkin是一个分布式的跟踪系统。它有助于收集数据需要解决潜在的问题在市微服架构的时机。它管理数据的收集和查找 .

该产品结合spring-cloud-sleuth使用较为简单, 集成很方便。 但是功能较简单。

支持技术栈:

  • spring cloud

以上是结合spring-cloud-sleuth支持的技术栈

pinpoint

由韩国团队naver团队开源,针对大规模分布式系统用链路监控,使用java写的工具。灵感来自短小精悍,帮助分析系统的总

体结构和内部组件如何被调用在分布式应用提供了一个很好的解决方案。

使用java探针字节码增加技术,实现对整个应用的监控 。 对应用零侵入

支持技术栈:

  • Tomcat 6+,Jetty 8/9,JBoss 6,Resin 4,Websphere 6+,Vertx 3.3+
  • Spring, Spring Boot (Embedded Tomcat, Jetty)
  • HTTP Client 3.x/4.x, HttpConnector, GoogleHttpClient, OkHttpClient, NingAsyncHttpClient
  • Thrift, Dubbo
  • mysql, oracle, mssql, cubrid,PostgreSQL, maria
  • arcus, memcached, redis, cassandra
  • MyBatis
  • DBCP, DBCP2, HIKARICP
  • gson, Jackson, Json Lib
  • log4j, Logback

skywalking

2015年由个人吴晟(华为开发者)开源 , 2017年加入Apache孵化器。

针对分布式系统的应用性能监控系统,特别针对微服务、cloud native和容器化(Docker, Kubernetes, Mesos)架构, 其核心是个分布式追踪系统。

使用java探针字节码增加技术,实现对整个应用的监控 。对应用零侵入

支持技术栈

  • Tomcat7+ , resin3+, jetty
  • spring boot ,spring mvc
  • strtuts2
  • spring RestTemplete ,spring-cloud-feign
  • okhttp , httpClient
  • msyql ,oracle , H2 , sharding-jdbc,PostgreSQL
  • dubbo,dubbox ,motan, gRpc ,
  • rocketMq , kafla
  • redis, mongoDB,memcached ,
  • elastic-job , Netflix Eureka , Hystric

总结

模拟了三种并发用户:500,750,1000。使用jmeter测试,每个线程发送30个请求,设置思考时间为10ms。使用的采样率为1,即100%,这边与生产可能有差别。

pinpoint默认的采样率为20,即50%,通过设置agent的配置文件改为100%。zipkin默认也是1。组合起来,一共有12种。