本例介绍Pinpoint告警的相关内容,Pinpoint参考【APM】Pinpoint 安装部署(一)
Pinpoint Web会定期检查应用程序的状态,并在满足某些预配置条件(规则)的情况下触发警报。
这些条件(默认情况下)由Web模块中的后台批处理过程每3分钟检查一次(默认情况下),使用的是最后5分钟的数据。一旦满足条件,批处理过程就会向注册到用户组的用户发送短信/电子邮件。
本例Pinpoint版本是:1.8.5,下载地址:https://github.com/naver/pinpoint/releases/tag/1.8.5
参考git文档:https://naver.github.io/pinpoint/alarm.html
参考博客:https://skyao.gitbooks.io/learning-pinpoint/content/alarm/code_implementation.html
Pinpoint告警原理
1、下载源码,通过源码解析:
Pinpoint中有一个匹处理类,BatchConfiguration.java,此类会进行批任务处理
1 @Configuration 2 @Conditional(BatchConfiguration.Condition.class) 3 @ImportResource("classpath:/batch/applicationContext-batch-schedule.xml") 4 public class BatchConfiguration{ 5 static class Condition implements ConfigurationCondition { 6 @Override 7 public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 8 ...... 9 Resource resource = context.getResourceLoader().getResource("classpath:/batch.properties") 10 ...... 11 final String enable = properties.getProperty("batch.enable"); 12 ...... 13 } 14 } 15 }
Condition中会读取配置文件batch.properties中的配置项batch.enable,默认是false。因此如果要开启批处理功能,必须设置batch.enable=true。
2、在Pinpoint中,在批处理任务配置文件(applicationContext-batch-schedule.xml)中,文件路径为:pinpoint/web/src/main/resources/batch/applicationContext-batch-schedule.xml,可以找到定义的任务
1 <task:scheduled-tasks scheduler="scheduler"> 2 <task:scheduled ref="batchJobLauncher" method="alarmJob" cron="0 0/3 * * * *" /> 3 <task:scheduled ref="batchJobLauncher" method="agentCountJob" cron="0 0 2 * * *" /> 4 <task:scheduled ref="batchJobLauncher" method="flinkCheckJob" cron="0 0/10 * * * *" /> 5 </task:scheduled-tasks> 6 7 <task:scheduler id="scheduler" pool-size="1"/>
配置文件中,定义了执行告警Job的时间。定义了一个线程池大小为1的调度器scheduler
3、在Pinpoint中,在告警任务配置文件(applicationContext-alarmJob.xml)中,文件路径为:pinpoint/web/src/main/resources/batch/applicationContext-alarmJob.xml,
reader:读取数据 => 通过用户配置的规则提供Checker,即异常校验器。
processor:处理数据 => 用Checker进行校验,标记异常状态。
writer:回写数据 => 判断Checker是否有异常情况,有则报警。
1 <batch:job id="alarmJob"> 2 <batch:step id="alarmPartitionStep"> 3 <batch:partition step="alarmStep" partitioner="alarmPartitioner"> 4 <batch:handler task-executor="alarmPoolTaskExecutorForPartition" /> 5 </batch:partition> 6 </batch:step> 7 <batch:listeners> 8 <batch:listener ref="jobFailListener"/> 9 </batch:listeners> 10 </batch:job> 11 12 <batch:step id="alarmStep"> 13 <batch:tasklet> 14 <batch:chunk reader="reader" processor="processor" writer="writer" commit-interval="1"/> 15 </batch:tasklet> 16 </batch:step> 17 18 <bean id="alarmPartitioner" class="com.navercorp.pinpoint.web.alarm.AlarmPartitioner"/> 19 <bean id="reader" class="com.navercorp.pinpoint.web.alarm.AlarmReader" scope="step"/> 20 <bean id="processor" class="com.navercorp.pinpoint.web.alarm.AlarmProcessor" scope="step"/> 21 <bean id="writer" class="com.navercorp.pinpoint.web.alarm.AlarmWriter" scope="step"/> 22 23 <task:executor id="alarmPoolTaskExecutorForPartition" pool-size="1" />
4、在回写数据类中AlarmWriter.java中发现,是通过注入AlarmMessageSender来发送消息
1 public class AlarmWriter implements ItemWriter<AlarmChecker> { 2 3 @Autowired(required = false) 4 private AlarmMessageSender alarmMessageSender = new EmptyMessageSender(); 5 6 @Autowired 7 private AlarmService alarmService; 8 9 ...... 10 11 // 发送消息 12 private void sendAlarmMessage(CheckerResult beforeCheckerResult, AlarmChecker checker) { 13 if (isTurnToSendAlarm(beforeCheckerResult)) { 14 if (checker.isSMSSend()) { 15 alarmMessageSender.sendSms(checker, beforeCheckerResult.getSequenceCount() + 1); 16 } 17 if (checker.isEmailSend()) { 18 alarmMessageSender.sendEmail(checker, beforeCheckerResult.getSequenceCount() + 1); 19 } 20 } 21 22 } 23 24 ...... 25 }
5、在AlarmMessageSender初始化的值是EmptyMessageSender,通过查看EmptyMessageSender发现此类只是一个空的实现,所有这里只要我们自己实现AlarmMessageSender就能发送告警消息
1 public class EmptyMessageSender implements AlarmMessageSender { 2 3 @Override 4 public void sendSms(AlarmChecker checker, int sequenceCount) { 5 } 6 7 @Override 8 public void sendEmail(AlarmChecker checker, int sequenceCount) { 9 } 10 11 }
Pinpoint告警开发
1、下载源码,导入Idea中。
2、由于查看pom文件,发现源码编译构建需要用到Maven3.5,JDK1.8,Java6,Java7,Java8,Java9,在开发环境中安装好对应的Maven版本,以及配置好JDK版本
1 <requireMavenVersion> 2 <version>3.5</version> 3 </requireMavenVersion> 4 <requireJavaVersion> 5 <version>1.8</version> 6 </requireJavaVersion> 7 <requireEnvironmentVariable> 8 <variableName>JAVA_HOME</variableName> 9 </requireEnvironmentVariable> 10 <requireEnvironmentVariable> 11 <variableName>JAVA_6_HOME</variableName> 12 </requireEnvironmentVariable> 13 <requireEnvironmentVariable> 14 <variableName>JAVA_7_HOME</variableName> 15 </requireEnvironmentVariable> 16 <requireEnvironmentVariable> 17 <variableName>JAVA_8_HOME</variableName> 18 </requireEnvironmentVariable> 19 <requireEnvironmentVariable> 20 <variableName>JAVA_9_HOME</variableName> 21 </requireEnvironmentVariable>
3、查看依赖,下载依赖jar包(部分依赖可以用相似版本替代)
4、实现和配置告警发消息类
为了使用告警功能,必须通过实现 com.navercorp.pinpoint.web.alarm.AlarmMessageSender并注册为spring managed bean 来实现自己的逻辑以便发送短信和邮件。当告警被触发时, AlarmMessageSender#sendEmail, 和 AlarmMessageSender#sendSms 方法将被调用。
AlarmMessageSenderImple.java 如下:
1 public class AlarmMessageSenderImple implements AlarmMessageSender { 2 3 private final Logger logger = LoggerFactory.getLogger(this.getClass()); 4 5 @Override 6 public void sendSms(AlarmChecker checker, int sequenceCount) { 7 List<String> receivers = userGroupService.selectPhoneNumberOfMember(checker.getuserGroupId()); 8 9 if (receivers.size() == 0) { 10 return; 11 } 12 13 for (String message : checker.getSmsMessage()) { 14 logger.info("send SMS : {}", message); 15 16 // TODO Implement logic for sending SMS 17 } 18 } 19 20 @Override 21 public void sendEmail(AlarmChecker checker, int sequenceCount) { 22 List<String> receivers = userGroupService.selectEmailOfMember(checker.getuserGroupId()); 23 24 if (receivers.size() == 0) { 25 return; 26 } 27 28 for (String message : checker.getEmailMessage()) { 29 logger.info("send email : {}", message); 30 31 // TODO Implement logic for sending email 32 } 33 } 34 }
发邮件方法,可以参考:【Mail】JavaMail介绍及发送邮件(一)
发短信需要对接第三方运营商。
注册AlarmMessageSenderImple,在applicationContext-batch.xml文件中注册
1 <bean id="alarmMessageSenderImple" class="com.navercorp.pinpoint.web.alarm.AlarmMessageSenderImple"/>
还在可以发邮件信息做成可配置形式,在batch.properties文件中提供smtp服务器信息和发送者的地址。在AlarmMessageSenderImple中进行使用
1 pinpoint.url= #pinpoint-web server url 2 alarm.mail.server.url= #smtp server address 3 alarm.mail.server.port= #smtp server port 4 alarm.mail.server.username= #username for smtp server authentication 5 alarm.mail.server.password= #password for smtp server authentication 6 alarm.mail.sender.address= #sender's email address 7 8 ex) 9 pinpoint.url=http://pinpoint.com 10 alarm.mail.server.url=stmp.server.com 11 alarm.mail.server.port=587 12 alarm.mail.server.username=pinpoint 13 alarm.mail.server.password=pinpoint 14 alarm.mail.sender.address=pinpoint_operator@pinpoint.com
在注册AlarmMessageSenderImple时,注入相关参数
<bean id="alarmMessageSenderImple" class="com.navercorp.pinpoint.web.alarm.AlarmMessageSenderImple"/> <property name="host" value="#{batchProps['alarm.mail.server.url'] ?: ''}" /> <property name="port" value="#{batchProps['alarm.mail.server.port'] ?: 587}" /> <property name="username" value="#{batchProps['alarm.mail.server.username'] ?: ''}" /> <property name="password" value="#{batchProps['alarm.mail.server.password'] ?: ''}" /> <property name="mailfrom" value="#{batchProps['alarm.mail.sender.address'] ?: ''}" /> </bean>
5、修改配置文件batch.properties
在batch.properties中将batch.enable
标志设置为true,开启批处理功能
1 batch.enable=true
batch.server.ip
当有多个精确的Web服务器时,可以进行配置以防止并发批处理操作。仅当服务器的IP地址与中设置的值相同时,才执行批处理batch.server.ip
。(将此设置为127.0.0.1将在所有Web服务器中启动批处理)
1 batch.server.ip=X.X.X.X
6、配置mysql,需要用到MYSQL来存储用户信息以告警规则等,设置MYSQL服务器并在jdbc.properties文件中配置连接信息。
在resources/sql中有2个文件,CreateTableStatement-mysql.sql和SpringBatchJobRepositorySchema-mysql.sql,用来创建表。
1 jdbc.driverClassName=com.mysql.jdbc.Driver 2 jdbc.url=jdbc:mysql://localhost:13306/pinpoint?characterEncoding=UTF-8 3 jdbc.username=admin 4 jdbc.password=admin
7、其他
a、可以在单独的过程中启动警报批处理 -只需使用Pinpoint-web模块内的applicationContext-alarmJob.xml文件启动弹簧批处理作业即可。
b、可以通过修改applicationContext-batch-schedule.xml文件中的cron表达式来更改批处理执行时间
1 <task:scheduled-tasks scheduler="scheduler"> 2 <task:scheduled ref="batchJobLauncher" method="alarmJob" cron="0 0/3 * * * *" /> 3 </task:scheduled-tasks>
c、改善警报批处理性能的方法 -警报批处理设计为可同时运行。如果您有许多注册了警报的应用程序,则可以通过pool-size
在applicationContext-batch.xml文件中进行修改来增加执行程序的线程池的大小。
1 <task:executor id="poolTaskExecutorForPartition" pool-size="1" />
8、配置Hbase及Zookeeper,参考:【APM】Pinpoint 安装部署(一),然后使用Maven打包项目,打包后,将pinpoint-web-1.8.5.war,放入tomcat中运行
Pinpoint告警使用
1、打开pinpoint网页,打开pinpoint配置
2、新增用户信息
3、新增用户组
4、添加用户到用户组
5、设置告警规则,测试可以使用TOTAL COUNT / 请求总数量超过多少就报警
6、页面上发起请求,超过请求次数
7、通过后台查看日志,或者是邮箱,可以发现告警已经实现
告警规则
-
SLOW COUNT / 慢请求数
当应用发出的慢请求数量超过配置阈值时触发。
-
SLOW RATE / 慢请求比例
当应用发出的慢请求百分比超过配置阈值时触发。
-
ERROR COUNT / 请求失败数
当应用发出的失败请求数量超过配置阈值时触发。
-
ERROR RATE / 请求失败率
当应用发出的失败请求百分比超过配置阈值时触发。
-
TOTAL COUNT / 总数量
当应用发出的所有请求数量超过配置阈值时触发。
以上规则中,请求是当前应用发送出去的,当前应用是请求的发起者。 以下规则中,请求是发送给当前应用的,当前应用是请求的接收者。
-
SLOW COUNT TO CALLEE / 被调用的慢请求数量
当发送给应用的慢请求数量超过配置阈值时触发。
-
SLOW RATE TO CALLEE / 被调用的慢请求比例
当发送给应用的慢请求百分比超过配置阈值时触发。
-
ERROR COUNT TO CALLEE / 被调用的请求错误数
当发送给应用的请求失败数量超过配置阈值时触发。
-
ERROR RATE TO CALLEE / 被调用的请求错误率
当发送给应用的请求失败百分比超过配置阈值时触发。
-
TOTAL COUNT TO CALLEE / 被调用的总数量
当发送给应用的所有请求数量超过配置阈值时触发。
下面两条规则和请求无关,只涉及到应用的状态
-
HEAP USAGE RATE / 堆内存使用率
当应用的堆内存使用率超过配置阈值时触发。
-
JVM CPU USAGE RATE / JVM CPU使用率
当应用的CPU使用率超过配置阈值时触发。