错误追踪系统Sentry在微服务环境的应用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/j16421881/article/details/87725204

Table of Contents

1. 什么是Sentry

2. 客户端接入

2.1 验证Sentry服务

2.2 DSN(Data Source Name)

2.3 客户端接入Sentry

3. 已知问题

3.1 网络问题

3.2 客户端吞吐能力


1. 什么是Sentry

       Sentry 是一个开源的实时错误追踪系统,支持 Python、Java、Go、Node等主流编程语言。下面直接通过Sentry控制台的一张图来直观的展示Sentry的便利之处。如图是Sentry控制台一个报错信息,包含了接入Sentry的项目名,发生问题的机器IP,问题的具体原因。尤其是微服务部署在多台机器上,通过Sentry给发现问题,定位问题带来了极大的方便。

2. 客户端接入

      这里使用了Sentry 版本7.1.0,由于网上搭建资料丰富,不再详细介绍。

2.1 验证Sentry服务

      搭建完毕后,本人就遇到过客户端调不通Sentry服务的现象,一度怀疑代码问题,后来才发现是网络问题。通过官方提供的Linux 命令工具:sentry-cli 可以快速的在客户端机器测试到Sentry的服务是否正常。

     sentry-cli安装详见: https://blog.sentry.io/2017/11/28/sentry-bash

     安装后先设置DSN环境变量,再通过Linux命令发送测试消息到Sentry服务器,然后到Sentry控制台查看是否收到消息。

    

$ export SENTRY_DSN=<your-dsn-goes-here>
$ sentry-cli send-event -m "Something happened"

     

2.2 DSN(Data Source Name)

    安装后由管理员在项目所属Group下面创建项目空间,配置该项目报错之后的邮件通知,给项目分配DSN。

     

如图,配置给哪些人发送报错邮件通知,便于相关负责人及时处理问题。

         

Sentry 服务通过DSN支持多用户、多团队、多应用管理,每个应用都对应一个 PROJECT_ID,以及用于身份认证的 PUBLIC_KEY 和 SECRET_KEY。 DSN如下所示,可以看到DSN中的key是一串类似UUID的字符,保证了DSN的唯一性。项目往自己的DSN地址发送错误消息,Sentry控制台就能看到这个项目的报错。

'{PROTOCOL}://{PUBLIC_KEY}:{SECRET_KEY}@{HOST}/{PATH}{PROJECT_ID}'
如下是一个实际的dsn地址:
http://a89eebecb6504e9ab8c39290e3a0edae:2a5640f21d4643f3ba23147168519d60@ip地址/54

    拿到这个DSN后我们就可以在Java客户端接入Sentry了。

2.3 客户端接入Sentry

   这里我们以Logback日志框架为例,其他接入可以参考Sentry官网。

   首先引入Maven依赖

<dependency>
	 <groupId>com.getsentry.raven</groupId>
	 <artifactId>raven-logback</artifactId>
	 <version>7.1.0</version>
</dependency>

Logback将执行日志事件输出的组件称为Appender,实现的Appender必须继承 ch.qos.logback.core.Appender 接口,引入Sentry实现的组件SentryAppender。查看SentryAppender源码,继承了基类ch.qos.logback.core.AppenderBase,而基类又实现了Appender接口。当我们在代码中通过logger.error()打印错误日志的时候,会同时将错误日志推送到Sentry系统,实现在SentryAppender的append方法里面。在logback.xml里面注册 SentryAppender,其中SENTRY_DSN对应该项目在Sentry里面分配的DSN,APP_ID对应在Sentry中的项目名。

protected void append(ILoggingEvent iLoggingEvent)
<appender name="Sentry" class="com.getsentry.raven.logback.SentryAppender">
       <dsn>${SENTRY_DSN}</dsn>
       <tags>APP:${APP_ID}</tags>
</appender>

<root level="ERROR">
       <appender-ref ref="Sentry"/>
</root>

其中xml中两个参数在不同的环境可以通过jvm参数动态设置:
 

-DAPP_ID=myapp
-DSENTRY_DSN=http://public_key:private_key@ip地址/81

3. 已知问题

3.1 网络问题

当客户端错误日志太多的时候发现Connection报错

2018-09-27 16:06:50.270 [raven-pool-2-thread-1] [WARN ] {"traceId":""}c.g.r.connection.AbstractConnection[lockDown:111] - Lockdown started for 10ms.
2018-09-27 16:06:50.280 [raven-pool-2-thread-1] [WARN ] {"traceId":""}c.g.r.connection.AbstractConnection[lockDown:128] - Lockdown ended.
2018-09-27 16:06:50.397 [raven-pool-2-thread-2] [WARN ] {"traceId":""}c.g.r.connection.AbstractConnection[send:81] - An exception due to the connection occurred, a lockdown will be initiated.
com.getsentry.raven.connection.ConnectionException: An exception occurred while submitting the event to the sentry server.
        at com.getsentry.raven.connection.HttpConnection.doSend(HttpConnection.java:132) ~[raven-7.1.0.jar:na]
        at com.getsentry.raven.connection.AbstractConnection.send(AbstractConnection.java:78) ~[raven-7.1.0.jar:na]
        at com.getsentry.raven.connection.AsyncConnection$EventSubmitter.run(AsyncConnection.java:144) [raven-7.1.0.jar:na]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_172]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_172]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_172]
Caused by: java.net.SocketException: Unexpected end of file from server
        at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:851) ~[na:1.8.0_172]
        at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678) ~[na:1.8.0_172]
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1587) ~[na:1.8.0_172]
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492) ~[na:1.8.0_172]
        at com.getsentry.raven.connection.HttpConnection.doSend(HttpConnection.java:124) ~[raven-7.1.0.jar:na]
        ... 5 common frames omitted

一种原因是网络不稳定造成的,客户端Sentry推送消息失败,错误信息丢失不会显示在Sentry台上。

查看官方文档,我们可以在DSN地址里面配置超时时间,来减少网络不稳定带来的影响,如下
http://public_key:private_key@ip地址/81?raven.timeout=30000

3.2 客户端吞吐能力

查看com.getsentry.raven.connection.AsyncConnection源码,AsyncConnection使用了ExecutorService线程池来处理错误消息的推送。若错误消息太多,线程池就会阻塞,消息无法及时推送到Sentry系统中去。

查看官方文档,通过在DSN地址里面添加raven.async.threads参数,自定义客户端Sentry线程池数。

http://public_key:private_key@ip地址/81?raven.async.threads=8

猜你喜欢

转载自blog.csdn.net/j16421881/article/details/87725204