千家信息网

如何用SpringBoot admin+Eureka+钉钉通知实现微服务监控

发表于:2024-11-22 作者:千家信息网编辑
千家信息网最后更新 2024年11月22日,本篇内容主要讲解"如何用SpringBoot admin+Eureka+钉钉通知实现微服务监控",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何用Spri
千家信息网最后更新 2024年11月22日如何用SpringBoot admin+Eureka+钉钉通知实现微服务监控

本篇内容主要讲解"如何用SpringBoot admin+Eureka+钉钉通知实现微服务监控",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何用SpringBoot admin+Eureka+钉钉通知实现微服务监控"吧!

SpringBoot admin+Eureka+钉钉通知

一、效果

登录账号+密码

监控服务

查看实时日志

钉钉通知

二、什么是Spring Boot Admin ?

Spring Boot Admin是一个开源社区项目,用于管理和监控SpringBoot应用程序。 应用程序作为Spring Boot Admin Client向为Spring Boot Admin Server注册(通过HTTP)或使用SpringCloud注册中心(例如Eureka,Consul)发现。 UI是的Vue.js应用程序,展示Spring Boot Admin Client的Actuator端点上的一些监控。服务端采用Spring WebFlux + Netty的方式。Spring Boot Admin为注册的应用程序提供以下功能:

  • 显示健康状况

  • 显示详细信息,例如

  • JVM和内存指标

  • micrometer.io指标

  • 数据源指标

  • 缓存指标

  • 显示构建信息编号

  • 关注并下载日志文件

  • 查看jvm system-和environment-properties

  • 查看Spring Boot配置属性

  • 支持Spring Cloud的postable / env-和/ refresh-endpoint

  • 轻松的日志级管理

  • 与JMX-beans交互

  • 查看线程转储

  • 查看http-traces

  • 查看auditevents

  • 查看http-endpoints

  • 查看计划任务

  • 查看和删除活动会话(使用spring-session)

  • 查看Flyway / Liquibase数据库迁移

  • 下载heapdump

  • 状态变更通知(通过电子邮件,Slack,Hipchat,......)

  • 状态更改的事件日志(非持久性)

三、原理

使用 Spring Boot Actuator 监控应用

四、集成 Eureka注册中心

1. 创建 eureka-server,自行google

2. 创建 spring-boot-admin

这是一个 Spring Boot Admin Server端。

pom.xml
    4.0.0            org.springframework.boot        spring-boot-starter-parent        2.1.6.RELEASE                 jar    spring-boot-admin    spring-boot-admin    Spring Boot Admin Server端             1.8        2.1.6        Greenwich.RELEASE                            org.springframework.boot            spring-boot-starter-web                            de.codecentric            spring-boot-admin-starter-server                            org.springframework.cloud            spring-cloud-starter-netflix-eureka-client                            org.springframework.boot            spring-boot-starter-test            test                            org.springframework.boot            spring-boot-starter-security                            org.jolokia            jolokia-core                                                    org.springframework.cloud                spring-cloud-dependencies                ${spring-cloud.version}                pom                import                                        de.codecentric                spring-boot-admin-dependencies                ${spring-boot-admin.version}                pom                import                                                                org.springframework.boot                spring-boot-maven-plugin                        
application.yml
spring:  application:    name: admin-serverserver:  port: 1300eureka:  client:    registryFetchIntervalSeconds: 5    service-url:      defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/  instance:    leaseRenewalIntervalInSeconds: 10    health-check-url-path: /actuator/healthmanagement:  endpoints:    web:      exposure:        include: "*"  endpoint:    health:      show-details: ALWAYS
启动类 SpringbootAdminServerApplication
@SpringBootApplication@EnableAdminServer@EnableEurekaClientpublic class ScAdminServerApplication {    public static void main(String[] args) {        SpringApplication.run( ScAdminServerApplication.class, args );    }}

3. 被监控端

被监控端需要放开端点

application.yml
spring:  application:    name: admin-clienteureka:  instance:    leaseRenewalIntervalInSeconds: 10    health-check-url-path: /actuator/health  client:    registryFetchIntervalSeconds: 5    service-url:      defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/management:  endpoints:    web:      exposure:        include: "*"  endpoint:    health:      show-details: ALWAYSserver:  port: 8762

admin 会自己拉取 Eureka 上注册的信息,主动去注册。

五、集成 Spring Security

Web应用程序中的身份验证和授权有多种方法,因此Spring Boot Admin不提供默认方法。默认情况下,spring-boot-admin-server-ui提供登录页面和注销按钮。我们结合 Spring Security 实现需要用户名和密码登录的安全认证。

springboot-admin工程的pom文件需要增加以下的依赖:

    org.springframework.boot    spring-boot-starter-security

在 spirngboot-admin工的配置文件 application.yml 中配置 spring security 的用户名和密码,这时需要在服务注册时带上 metadata-map 的信息,如下:

spring:  security:    user:      name: "admin"      password: "admin"      eureka:  instance:    metadata-map:      user.name: ${spring.security.user.name}      user.password: ${spring.security.user.password}      startup: ${random.int}    #needed to trigger info and endpoint update after restart

写一个配置类SecuritySecureConfig继承WebSecurityConfigurerAdapter,配置如下:

/** * security配置 * @author wangjiafang * @date 2019/10/10 */@Configurationpublic class SecuritySecureConfig extends WebSecurityConfigurerAdapter {    private final String adminContextPath;    public SecuritySecureConfig(AdminServerProperties adminServerProperties) {        this.adminContextPath = adminServerProperties.getContextPath();    }    @Override    protected void configure(HttpSecurity http) throws Exception {        // @formatter:off        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();        successHandler.setTargetUrlParameter("redirectTo");        successHandler.setDefaultTargetUrl(adminContextPath + "/");        http.authorizeRequests()                .antMatchers(adminContextPath + "/assets/**").permitAll()                .antMatchers(adminContextPath + "/login").permitAll()                .anyRequest().authenticated()                .and()                .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()                .logout().logoutUrl(adminContextPath + "/logout").and()                .httpBasic().and()                .csrf()                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())                .ignoringRequestMatchers(                        new AntPathRequestMatcher(adminContextPath + "/instances", HttpMethod.POST.toString()),                        new AntPathRequestMatcher(adminContextPath + "/instances/*", HttpMethod.DELETE.toString()),                        new AntPathRequestMatcher(adminContextPath + "/actuator/**")                );        // @formatter:on    }}

重新访问 http:localhost:1300 会出现登录界面,密码是配置文件中配置好的,账号 admin 密码 admin

六、通知

自定义通知+钉钉通知

1、创建钉钉机器人,拿到token,怎么创建钉钉机器人,请自行google2、下载sdk

钉钉官方提供了统一的SDK,使用SDK可以便捷的调用服务端API,但没有放到公共maven仓库中,需要自行下载后导入到项目,或者上传到自己的搭建的nexus私服中

3、自定义的通知器

通过扩展 AbstractEventNotifier或AbstractStatusChangeNotifier。在springboot-admin-server工程中编写一个自定义的通知器:

import com.dingtalk.api.DefaultDingTalkClient;import com.dingtalk.api.DingTalkClient;import com.dingtalk.api.request.OapiRobotSendRequest;import com.taobao.api.ApiException;import de.codecentric.boot.admin.server.domain.entities.Instance;import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;import de.codecentric.boot.admin.server.domain.events.InstanceEvent;import de.codecentric.boot.admin.server.domain.events.InstanceStatusChangedEvent;import de.codecentric.boot.admin.server.notify.AbstractEventNotifier;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import reactor.core.publisher.Mono;/** * 钉钉通知 * @author wangjiafang * @date 2019/10/10 */@Component@Slf4jpublic class CustomNotifier  extends AbstractEventNotifier {    /**     * 消息模板     */    private static final String template = "服务名:%s(%s) \n状态:%s(%s) \n服务ip:%s";    @Value("${spring.admin.ding-talk-token}")    private String dingTalkToken;    public CustomNotifier(InstanceRepository repository) {        super(repository);    }    @Override    protected Mono doNotify(InstanceEvent event, Instance instance) {        return Mono.fromRunnable(() -> {            if (event instanceof InstanceStatusChangedEvent) {                log.info("Instance {} ({}) is {}", instance.getRegistration().getName(), event.getInstance(),                        ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus());                String status = ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus();                String messageText = null;                switch (status) {                    // 健康检查没通过                    case "DOWN":                        log.info("发送 健康检查没通过 的通知!");                        messageText = String.format(template, instance.getRegistration().getName(),event.getInstance(), ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(),"健康检查没通过",instance.getRegistration().getServiceUrl());                        this.sendMessage(messageText);                        break;                    // 服务离线                    case "OFFLINE":                        log.info("发送 服务离线 的通知!");                        messageText = String.format(template, instance.getRegistration().getName(),event.getInstance(), ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(),"服务离线",instance.getRegistration().getServiceUrl());                        this.sendMessage(messageText);                        break;                    //服务上线                    case "UP":                        log.info("发送 服务上线 的通知!");                        messageText = String.format(template, instance.getRegistration().getName(),event.getInstance(), ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(),"服务上线",instance.getRegistration().getServiceUrl());                        this.sendMessage(messageText);                        break;                    // 服务未知异常                    case "UNKNOWN":                        log.info("发送 服务未知异常 的通知!");                        messageText = String.format(template, instance.getRegistration().getName(),event.getInstance(), ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(),"服务未知异常",instance.getRegistration().getServiceUrl());                        this.sendMessage(messageText);                        break;                    default:                        break;                }            } else {                log.info("Instance {} ({}) {}", instance.getRegistration().getName(), event.getInstance(),                    event.getType());            }        });    }    /**     * 发送消息     * @param messageText     */    private void sendMessage(String messageText){        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/robot/send?access_token="+dingTalkToken);        OapiRobotSendRequest request = new OapiRobotSendRequest();        request.setMsgtype("text");        OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();        text.setContent(messageText);        request.setText(text);        try {            client.execute(request);        } catch (ApiException e) {            log.info("[ERROR] sendMessage", e);        }    }}

七 查看实时日志

要在springbootadmin面板中查看实时日志,需要指定项目中日志输出的地址,比如我的日志是在/logs/项目名称/项目名称-info.log下

logging:  file: /logs/${spring.application.name}/${spring.application.name}-info.log

到此,相信大家对"如何用SpringBoot admin+Eureka+钉钉通知实现微服务监控"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0