創(chuàng)建Server
SpringBootAdmin通過收集actuator暴露出來的服務信息以及通過心跳檢測的機制判斷服務的運行狀況忆蚀。
1.引入依賴
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.2.0</version>
</dependency>
2. 啟動類手動裝配AdminServer
@EnableAdminServer
@SpringBootApplication
public class MicroAdminApplication {
public static void main(String[] args) {
SpringApplication.run(MicroAdminApplication.class, args);
}
}
3. 配置服務發(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
服務器端配置完畢今缚!
4. 接入SpringSecurity
保證登錄安全瞬项,可以不接
引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
指定登錄頁面為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不需要重復引入
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.2.0</version>
</dependency>
2. 配置暴露的端點信息
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: ALWAYS
[注意]
默認會檢查redis的健康狀況,如果你的服務沒有依賴redis何荚,需要額外增加配置囱淋,關掉redis的健康檢查。否則會報異常餐塘。
management:
health:
redis:
enabled: false
依次啟動Server和Client妥衣,瀏覽器登錄{port}訪問springBootAdmin,此時服務已經(jīng)接入成功
應用詳情可查看應用具體的狀況
Server端使用報警提示功能
接入郵箱報警提示
引入依賴
<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
【注意】
此處的郵箱密碼不是我們設定的郵箱密碼,需要登錄到對應的郵箱官網(wǎng)去設置smtp的授權碼戒傻,此處參照百度百科https://jingyan.baidu.com/article/295430f1fc28a60c7e0050f9.html
再次重啟admin Server 如果有服務發(fā)生任何變動會給配置的郵箱發(fā)送郵件
eg:
自定義報警
SpringBootAdmin 發(fā)送郵件的原理是基于事件的監(jiān)聽機制税手,類似于觀察者模式,具體的類
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;
}
/**
* 服務發(fā)送變動需纳,會調(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
我們可以在自己項目目錄下創(chuàng)建模板進行替換芦倒。
2. 更改郵件級別
不知道標題寫啥,就寫級別吧候齿,默認情況下服務的上線熙暴,下線,離線慌盯,未知周霉,等等狀態(tài)都會發(fā)郵件,服務的狀態(tài)在類Instance的StatusInfo里面使用6個String類型的常量來進行描述
部分源碼:
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. 做點別的?
有時候我們想既發(fā)送郵件灭必,也發(fā)送短信的形式來保證服務出現(xiàn)問題第一時間感知狞谱,我們可以自己編寫一個類繼承AbstractStatusChangeNotifier
實現(xiàn)onNotify
方法具體寫自己的短信邏輯就可以了,但是我們會發(fā)現(xiàn)禁漓,這樣操作的話跟衅,每次只會發(fā)送短信,不會發(fā)送默認的郵件了播歼,這是由于mailNotifier
使用自動裝配機制(不了解自動裝配的可以查看這篇文章http://www.reibang.com/p/c56c34c1c876
)伶跷,并通過@ConditionOnMissingBean
注解控制,如果Spring容器中有AbstractStatusChangeNotifier
實例了,就不會注入mailNotifier
,具體的解決方案可以是這樣的叭莫,復制他的代碼蹈集,然后去掉@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)控
這里只說一點點雇初,就是我們生產(chǎn)環(huán)境拢肆,一般SpringBootAdmin Server也需要進行集群部署,但是如果服務發(fā)生問題靖诗,相同的郵件會發(fā)送多份郭怪,所以需要使用分布式鎖的機制,如果你的分布式鎖是基于AOP實現(xiàn)刊橘,不能直接放在onNotify方法上移盆,因為這個方法的訪問權限是protected,需要將方法的訪問級別提升為public,可能也不好使,還是使用編碼的形式吧~