H__D  

  本例介绍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版本

    

    下面是pom.xml文件中的内容,需要Maven 3.5,Maven不是3.5可以进行修改

 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包(部分依赖可以用相似版本替代),且对pinpoint/pom.xml文件进行修改,是项目能运行打包。

    a、修改spotbugs-exclude.xml,位子,此内容有2个地方要替换

1 <!--<excludeFilterFile>${maven.multiModuleProjectDirectory}/spotbugs-exclude.xml</excludeFilterFile>-->
2 <!-- 改为 -->
3 <excludeFilterFile>${basedir}/spotbugs-exclude.xml</excludeFilterFile>

    b、插件注释掉

 1 <!--<plugin>-->
 2     <!--<groupId>org.apache.maven.plugins</groupId>-->
 3     <!--<artifactId>maven-jxr-plugin</artifactId>-->
 4     <!--<version>2.5</version>-->
 5     <!--<inherited>false</inherited>-->
 6     <!--<configuration>-->
 7         <!--<aggregate>true</aggregate>-->
 8         <!--<inputEncoding>${encoding}</inputEncoding>-->
 9         <!--<outputEncoding>${encoding}</outputEncoding>-->
10         <!--<windowTitle>Pinpoint ${project.version} Cross Reference</windowTitle>-->
11         <!--<docTitle>Pinpoint ${project.version} Cross Reference</docTitle>-->
12     <!--</configuration>-->
13 <!--</plugin>-->

    c、下载不下来直接注释掉

 1 <!-- 注释 -->
 2 <!--<profile>-->
 3     <!--<id>klocwork</id>-->
 4     <!--<build>-->
 5         <!--<plugins>-->
 6             <!--<plugin>-->
 7                 <!--<groupId>com.klocwork.ps</groupId>-->
 8                 <!--<artifactId>kwmaven</artifactId>-->
 9                 <!--<version>2.1.1</version>-->
10                 <!--<configuration>-->
11                     <!--<buildspec_filename>${KWINJECT_OUT_PATH}</buildspec_filename>-->
12                 <!--</configuration>-->
13                 <!--<executions>-->
14                     <!--<execution>-->
15                         <!--<phase>validate</phase>-->
16                         <!--<goals>-->
17                             <!--<goal>run</goal>-->
18                         <!--</goals>-->
19                     <!--</execution>-->
20                 <!--</executions>-->
21             <!--</plugin>-->
22 
23         <!--</plugins>-->
24     <!--</build>-->
25 <!--</profile>-->

    d、修改bootsrap-java9.pom文件

1 <!-- <jdk.version>9</jdk.version> -->
2 <!-- 修改为 -->
3 <jdk.version>1.9</jdk.version>

  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     @Autowired
 6     UserGroupService userGroupService;
 7 
 8     @Override
 9     public void sendSms(AlarmChecker checker, int sequenceCount) {
10 
11         List<String> receivers = userGroupService.selectPhoneNumberOfMember(checker.getuserGroupId());
12         logger.info(" =============准备发送消息=============== " + receivers.size());
13 
14         if (receivers.size() == 0) {
15             return;
16         }
17         List<String> smsList = checker.getSmsMessage();
18         for (String message : smsList) {
19             logger.info("send SMS : {}", message);
20             // TODO Implement logic for sending SMS
21             for (String receiver : receivers) {
22                 logger.info("send email receiver : {}", receiver);
23             }
24         }
25     }
26 
27     @Override
28     public void sendEmail(AlarmChecker checker, int sequenceCount) {
29 
30         List<String> receivers = userGroupService.selectEmailOfMember(checker.getuserGroupId());
31         logger.info(" ==============准备发送邮件=============== " + receivers.size());
32 
33         if (receivers.size() == 0) {
34             return;
35         }
36 
37         String message = checker.getEmailMessage();
38         logger.info("send email : {}", message);
39 
40         // TODO Implement logic for sending email
41         for (String receiver : receivers) {
42             logger.info("send email receiver : {}", receiver);
43         }
44     }
45 }

    发邮件方法,可以参考:【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时,注入相关参数

 1 @Value("#{batchProps['alarm.mail.server.url'] ?: ''}")
 2 String host;
 3 @Value("#{batchProps['alarm.mail.server.port'] ?: 587}")
 4 String port;
 5 @Value("#{batchProps['alarm.mail.server.username'] ?: ''}")
 6 String username;
 7 @Value("#{batchProps['alarm.mail.server.password'] ?: ''}")
 8 String password;
 9 @Value("#{batchProps['alarm.mail.sender.address'] ?: ''}")
10 String mailfrom;

  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使用率超过配置阈值时触发。

 

 

  

posted on 2019-11-28 11:13  H__D  阅读(3899)  评论(3编辑  收藏  举报