SkyWalking实现告警规则的通知及SkyWalking高可用部署

952 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情

一、SkyWalking实现告警规则的通知

通过SkyWalking虽然可以实现监控我们服务的一些告警信息,但是我们总不可能一直看着页面用人力的方式去监控告警状态,这样实在废人啊。实际上不用这么麻烦,SkyWalking已经给我们想到了这一点,其提供了一个webhook的功能,他可以将告警信息发送到我们指定的服务地址,然后我们再通过微信、钉钉、短信、邮件等方式通知运维人员,专业就可以做到如果有告警可以很快的告诉运维人员的功能。

1-1、Webhook(网络钩子)

Webhook可以简单理解为是一种Web层面的回调机制,通常由一些事件触发,与代码中的事件回调类似,只不过是Web层面的。由于是Web层面的,所以当事件发生时,回调的不再是代码中的方法或函数,而是服务接口。例如,在告警这个场景,告警就是一个事件。当该事件发生时,SkyWalking就会主动去调用一个配置好的接口,该接口就是所谓的Webhook。

SkyWalking的告警消息会通过 HTTP 请求进行发送,请求方法为 POST,Content-Type 为 application/json,其JSON 数据实基于List<List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage>进行序列化的。JSON数据示例:

image.png

需要注意的是,以上json数据的格式需要看下当前SkyWalking的版本是否匹配,不同版本json的key可能不太一样,这样我们在接受数据的时候,如果对应不上就无法正常接收数据,报400异常了。因此最好使用对应版本提供的List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage

字段说明:

  • scopeId、scope:所有可用的 Scope 详见 org.apache.skywalking.oap.server.core.source.DefaultScopeDefine
  • name:目标 Scope 的实体名称
  • id0:Scope 实体的 ID
  • id1:保留字段,目前暂未使用
  • ruleName:告警规则名称
  • alarmMessage:告警消息内容
  • startTime:告警时间,格式为时间戳

我这边使用的是8.5.0,可以去github上搜一下AlarmMessage,找到AlarmMessage

image.png

进去之后可以看到这个类的相关属性

image.png 我们就可以使用如上类,作为我们接收SkyWalking回调告警通知的接收参数。

1-2、邮件告警功能实践

根据以上两个小节的介绍,可以得知:SkyWalking是不支持直接向邮箱、短信等服务发送告警信息的,SkyWalking只会在发生告警时将告警信息发送至配置好的Webhook接口。

但我们总不能人工盯着该接口的日志信息来得知服务是否发生了告警,因此我们需要在该接口里实现发送邮件或短信等功能,从而达 到个性化的告警通知。

接下来开始动手实践,这里基于Spring Boot进行实现。首先是添加依赖:

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-mail</artifactId> 
</dependency>

配置邮箱服务:

#邮箱配置
spring:
  mail:
    host: smtp.163.com
    #发送者邮箱账号
    username: 你的邮箱@163.com
    #发送者密钥
    password: 你的邮箱服务密钥
    default-encoding: utf-8
    port: 465   #端口号465或587
    protocol: smtp
    properties:
      mail:
        debug:
          false
        smtp:
          socketFactory:
            class: javax.net.ssl.SSLSocketFactory

根据SkyWalking发送的JSON数据定义一个DTO,用于接口接收数据:

@Data
public class SwAlarmDTO {

    private Integer scopeId;
    private String scope;
    private String name;
    private Integer id0;
    private Integer id1;
    private String ruleName;
    private String alarmMessage;
    private Long startTime;
}

接着定义一个接口,实现接收SkyWalking的告警通知,并将数据发送至邮箱:

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/alarm")
public class SwAlarmController {

    private final JavaMailSender sender;

    @Value("${spring.mail.username}")
    private String from;

    /**
     * 接收skywalking服务的告警通知并发送至邮箱
     */
    @PostMapping("/receive")
    public void receive(@RequestBody List<SwAlarmDTO> alarmList) {
        SimpleMailMessage message = new SimpleMailMessage();
        // 发送者邮箱
        message.setFrom(from);
        // 接收者邮箱
        message.setTo(from);
        // 主题
        message.setSubject("告警邮件");
        String content = getContent(alarmList);
        // 邮件内容
        message.setText(content);
        sender.send(message);
        log.info("告警邮件已发送...");
    }

    private String getContent(List<SwAlarmDTO> alarmList) {
        StringBuilder sb = new StringBuilder();
        for (SwAlarmDTO dto : alarmList) {
            sb.append("scopeId: ").append(dto.getScopeId())
                    .append("\nscope: ").append(dto.getScope())
                    .append("\n目标 Scope 的实体名称: ").append(dto.getName())
                    .append("\nScope 实体的 ID: ").append(dto.getId0())
                    .append("\nid1: ").append(dto.getId1())
                    .append("\n告警规则名称: ").append(dto.getRuleName())
                    .append("\n告警消息内容: ").append(dto.getAlarmMessage())
                    .append("\n告警时间: ").append(dto.getStartTime())
                    .append("\n\n---------------\n\n");
        }

        return sb.toString();
    }
}

最后将该接口配置到SkyWalking中,Webhook的配置位于config/alarm-settings.yml文件的末尾,格式为http://{ip}:{port}/{uri}。如下示例:

[root@ip-236-048 skywalking]# vim config/alarm-settings.yml 
webhooks: - http://127.0.0.1:9134/alarm/receive

二、SkyWalking高可用部署

在大多数生产环境中,后端应用需要支持高吞吐量并且支持高可用来保证服务的稳定,所以你始终需要在生产环境进行集群管理。 Skywalking集群是将skywalking oap作为一个服务注册到nacos上,只要skywalking oap服务没有全部宕机,保证有一个skywalking oap在运行,就能进行跟踪。

搭建一个skywalking oap集群需要:

(1)至少一个Nacos(也可以是nacos集群)

(2)至少一个ElasticSearch/mysql(也可以是es/msql集群)

(3)至少2个skywalking oap服务;

(4)至少1个UI(UI也可以集群多个,用Nginx代理统一入口)

2-1、修改config/application.yml文件

使用nacos作为注册中心

image.png 修改nacos配置

image.png

可以选择性修改监听端口

image.png

修改存储策略,使用elasticsearch7作为storage

image.png

image.png

2-2、配置ui服务webapp.yml文件的listOfServers,写两个地址

image.png

3-3、启动服务测试

启动Skywalking服务,指定springboot应用的jvm参数,需要在启动的时候添加对应的ip+port.

-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.3.10:11800,192.168.3.12:11800