SpringBootAdmin微服務(wù)監(jiān)控

創(chuàng)建Server

SpringBootAdmin通過(guò)收集actuator暴露出來(lái)的服務(wù)信息以及通過(guò)心跳檢測(cè)的機(jī)制判斷服務(wù)的運(yùn)行狀況。

1.引入依賴

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-server</artifactId>
    <version>2.2.0</version>
</dependency>

2. 啟動(dòng)類手動(dòng)裝配AdminServer

@EnableAdminServer
@SpringBootApplication
public class MicroAdminApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(MicroAdminApplication.class, args);
    }
 
}

3. 配置服務(wù)發(fā)現(xiàn)

eureka

eureka:
  instance:
    prefer-ip-address: true
    lease-renewal-interval-in-seconds: 5
    lease-expiration-duration-in-seconds: 10
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
  client:
    fetch-registry: true
    registry-fetch-interval-seconds: 5
    serviceUrl:
      defaultZone: http://10.2.1.5:9001/eureka/,http://10.2.1.6:9001/eureka/

nacos

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.174.137:8848

服務(wù)器端配置完畢!

4. 接入SpringSecurity

保證登錄安全,可以不接

引入依賴
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
指定登錄頁(yè)面為SpringBootAdmin
@Configuration
public 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" );
 
        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().disable();
    }
}
配置登錄密碼
spring:
  security:
    user:
      name: 'admin'
      password: 'admin'

Client接入

1. 引入依賴

該依賴已經(jīng)包含spring-boot-starter-actuator不需要重復(fù)引入

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.2.0</version>
</dependency>

2. 配置暴露的端點(diǎn)信息

management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      show-details: ALWAYS

[注意]
默認(rèn)會(huì)檢查redis的健康狀況,如果你的服務(wù)沒(méi)有依賴redis,需要額外增加配置,關(guān)掉redis的健康檢查。否則會(huì)報(bào)異常。

management:
  health:
    redis:
      enabled: false

依次啟動(dòng)Server和Client,瀏覽器登錄{server.ip}:{port}訪問(wèn)springBootAdmin,此時(shí)服務(wù)已經(jīng)接入成功


應(yīng)用詳情可查看應(yīng)用具體的狀況

Server端使用報(bào)警提示功能

接入郵箱報(bào)警提示

引入依賴
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
配置郵箱信息
spring:
  boot:
    admin:
      notify:
        mail:
          to: yuwenbo10@jd.com
          from: 18629015421@163.com
  mail:
    host: smtp.163.com
    password: '******'
    username: 18629015421@163.com

【注意】
此處的郵箱密碼不是我們?cè)O(shè)定的郵箱密碼,需要登錄到對(duì)應(yīng)的郵箱官網(wǎng)去設(shè)置smtp的授權(quán)碼,此處參照百度百科https://jingyan.baidu.com/article/295430f1fc28a60c7e0050f9.html

再次重啟admin Server 如果有服務(wù)發(fā)生任何變動(dòng)會(huì)給配置的郵箱發(fā)送郵件
eg:


自定義報(bào)警

SpringBootAdmin 發(fā)送郵件的原理是基于事件的監(jiān)聽機(jī)制,類似于觀察者模式,具體的類
de.codecentric.boot.admin.server.notify.MailNotifier
部分源碼如下:

public class MailNotifier extends AbstractStatusChangeNotifier {
    private final JavaMailSender mailSender;
    private final TemplateEngine templateEngine;
    private String[] to = new String[]{"root@localhost"};
    private String[] cc = new String[0];
    private String from = "Spring Boot Admin <noreply@localhost>";
    private Map<String, Object> additionalProperties = new HashMap();
    @Nullable
    private String baseUrl;
    private String template = "classpath:/META-INF/spring-boot-admin-server/mail/status-changed.html";
 
    public MailNotifier(JavaMailSender mailSender, InstanceRepository repository, TemplateEngine templateEngine) {
        super(repository);
        this.mailSender = mailSender;
        this.templateEngine = templateEngine;
    }
 
    /**
     * 服務(wù)發(fā)送變動(dòng),會(huì)調(diào)用該方法發(fā)送郵件
     */
    protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
        return Mono.fromRunnable(() -> {
            Context ctx = new Context();
            ctx.setVariables(this.additionalProperties);
            ctx.setVariable("baseUrl", this.baseUrl);
            ctx.setVariable("event", event);
            ctx.setVariable("instance", instance);
            ctx.setVariable("lastStatus", this.getLastStatus(event.getInstance()));
 
            try {
                MimeMessage mimeMessage = this.mailSender.createMimeMessage();
                MimeMessageHelper message = new MimeMessageHelper(mimeMessage, StandardCharsets.UTF_8.name());
                message.setText(this.getBody(ctx).replaceAll("\\s+\\n", "\n"), true);
                message.setSubject(this.getSubject(ctx));
                message.setTo(this.to);
                message.setCc(this.cc);
                message.setFrom(this.from);
                this.mailSender.send(mimeMessage);
            } catch (MessagingException var6) {
                throw new RuntimeException("Error sending mail notification", var6);
            }
        });
    }
 
 
.....次數(shù)省略若干行
 
 
}

1.自定義郵件模板

可以看出郵件模板的存放路徑是

/META-INF/spring-boot-admin-server/mail/status-changed.html
我們可以在自己項(xiàng)目目錄下創(chuàng)建模板進(jìn)行替換。

2. 更改郵件級(jí)別

不知道標(biāo)題寫啥,就寫級(jí)別吧,默認(rèn)情況下服務(wù)的上線,下線,離線,未知,等等狀態(tài)都會(huì)發(fā)郵件,服務(wù)的狀態(tài)在類Instance的StatusInfo里面使用6個(gè)String類型的常量來(lái)進(jìn)行描述

部分源碼:

public final class StatusInfo implements Serializable {
 
   public static final String STATUS_UNKNOWN = "UNKNOWN";
 
   public static final String STATUS_OUT_OF_SERVICE = "OUT_OF_SERVICE";
 
   public static final String STATUS_UP = "UP";
 
   public static final String STATUS_DOWN = "DOWN";
 
   public static final String STATUS_OFFLINE = "OFFLINE";
 
   public static final String STATUS_RESTRICTED = "RESTRICTED";
 
   .....
}

我們可以繼承抽象類AbstractStatusChangeNotifier并重寫doNotify方法,定制化郵件發(fā)送。

3. 做點(diǎn)別的?

有時(shí)候我們想既發(fā)送郵件,也發(fā)送短信的形式來(lái)保證服務(wù)出現(xiàn)問(wèn)題第一時(shí)間感知,我們可以自己編寫一個(gè)類繼承AbstractStatusChangeNotifier實(shí)現(xiàn)onNotify方法具體寫自己的短信邏輯就可以了,但是我們會(huì)發(fā)現(xiàn),這樣操作的話,每次只會(huì)發(fā)送短信,不會(huì)發(fā)送默認(rèn)的郵件了,這是由于mailNotifier使用自動(dòng)裝配機(jī)制(不了解自動(dòng)裝配的可以查看這篇文章http://www.itdecent.cn/p/c56c34c1c876
),并通過(guò)@ConditionOnMissingBean注解控制,如果Spring容器中有AbstractStatusChangeNotifier實(shí)例了,就不會(huì)注入mailNotifier,具體的解決方案可以是這樣的,復(fù)制他的代碼,然后去掉@ConditionOnMissingBean注解就可以了。

@Configuration
public class BeanFactory {
 
 
    @AutoConfigureBefore({AdminServerNotifierAutoConfiguration.NotifierTriggerConfiguration.class, AdminServerNotifierAutoConfiguration.CompositeNotifierConfiguration.class})
    @ConditionalOnBean({MailSender.class})
    public static class MailNotifierConfiguration {
        private final ApplicationContext applicationContext;
 
        public MailNotifierConfiguration(ApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
        }
 
        @Bean
        @ConfigurationProperties("spring.boot.admin.notify.mail")
        public MailNotifier mailNotifier(JavaMailSender mailSender, InstanceRepository repository) {
            return new MailNotifier(mailSender, repository, this.mailNotifierTemplateEngine());
        }
 
        @Bean
        public TemplateEngine mailNotifierTemplateEngine() {
            SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
            resolver.setApplicationContext(this.applicationContext);
            resolver.setTemplateMode(TemplateMode.HTML);
            resolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
            SpringTemplateEngine templateEngine = new SpringTemplateEngine();
            templateEngine.addTemplateResolver(resolver);
            return templateEngine;
        }
    }
}

4.分布式監(jiān)控

這里只說(shuō)一點(diǎn)點(diǎn),就是我們生產(chǎn)環(huán)境,一般SpringBootAdmin Server也需要進(jìn)行集群部署,但是如果服務(wù)發(fā)生問(wèn)題,相同的郵件會(huì)發(fā)送多份,所以需要使用分布式鎖的機(jī)制,如果你的分布式鎖是基于AOP實(shí)現(xiàn),不能直接放在onNotify方法上,因?yàn)檫@個(gè)方法的訪問(wèn)權(quán)限是protected,需要將方法的訪問(wèn)級(jí)別提升為public,可能也不好使,還是使用編碼的形式吧~

參考鏈接:
https://www.cnblogs.com/forezp/p/10242004.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容