前言
上一節為springboot項目添加springboot-admin監控 學習了基於springboot1.5自己注冊到admin的方法。接下來學習結合Eureka使用以及2.0的改變。
1.5spring-boot-admin集成eureka
我們繼續上一節的項目修改,admin-server依賴修改如下
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
修改啟動類,添加
@EnableDiscoveryClient
@EnableAdminServer
修改配置文件application.properties
server.port=8081
spring.application.name=admin-server
eureka.client.serviceUrl.defaultZone=${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/
management.security.enabled=false
注意,這里的eureka server要提前啟動。具體細節,參見SpringCloud入門1-服務注冊與發現(Eureka)
到這里就結束,可以直接啟動。admin會自己拉取Eureka上注冊的app信息,主動去注冊。這也是唯一區別之前手動注冊的地方,就是client端不需要admin-client的依賴,也不需要配置admin地址了,一切全部由admin-server自己實現。這樣的設計對環境變化很友好,不用改了admin-server后去改所有app的配置了。
spring-boot-admin2.0的巨變
以為2.0比1.5區別不大,也確實不很大。關於client主動注冊的部分沒有變化。
這里,重新學習一遍,並添加上安全登錄功能。
新建一個springboot項目
項目地址:
https://github.com/Ryan-Miao/spring-cloud-demo/tree/master/admin-server
添加spring-boot-admin-server, 最終pom依賴如下
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-boot-admin.version>2.0.0</spring-boot-admin.version>
<spring-cloud.version>Finchley.RC2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<!--還沒有發布-->
<!--<dependency>-->
<!--<groupId>de.codecentric</groupId>-->
<!--<artifactId>spring-boot-admin-server-cloud</artifactId>-->
<!--</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-dependencies</artifactId>
<version>${spring-boot-admin.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>central</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<name>aliyun</name>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
注意到里面添加spring cloud eureka的依賴,我們也把admin給注冊到eureka。
這次的配置文件比較復雜
spring:
application:
name: admin-server
profiles:
active:
- secure
# tag::configuration-eureka[]
eureka: #<1>
instance:
leaseRenewalIntervalInSeconds: 10
health-check-url-path: /actuator/health #2.0后actuator的地址發生了變化
client:
registryFetchIntervalSeconds: 5
serviceUrl:
defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/
# 2.0開始,actuator默認不開放,所以要設置為開放
management:
endpoints:
web:
exposure:
include: "*" #<2>
endpoint:
health:
show-details: ALWAYS
server:
port: 8081
# end::configuration-eureka[]
---
spring:
profiles: insecure
---
# admin登錄的用戶名和密碼
spring:
profiles: secure
security:
user:
name: "user"
password: "password"
# 注冊給eureka的時候告訴eureka自己的密碼
eureka:
instance:
metadata-map:
"user.name": ${spring.security.user.name} #These two are needed so that the server
"user.password": ${spring.security.user.password} #can access the protected client endpoints
首先,我們同時支持兩種安全配置,一種沒有安全認證,一種有。注意到前面的依賴pom里有security的依賴。針對security方案,需要配置用戶名和密碼。
其次,配置了eureka client相關參數,把自己注冊到eureka里。
然后,關於actuator的端點接口,設置為全部開放。
最后,設置我們的用戶名和密碼,並把用戶名和密碼放到eureka里,方便識別。
配置security的安全過濾
最終的啟動類如下
@EnableDiscoveryClient
@EnableAdminServer
@SpringBootApplication
public class AdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(AdminServerApplication.class, args);
}
@Profile("insecure")
@Configuration
public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()//
.and().csrf().disable();
}
}
@Profile("secure")
@Configuration
public static 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();
// @formatter:on
}
}
}
和之前沒啥不同,唯一的區別是添加了安全認證相關的,即采用secure模式的時候必須輸入用戶名和密碼。
啟動
我們啟動並選擇激活配置環境secure
訪問localhost:8081
登錄
詳細頁
界面確實比1.5好很多啊。
新建一個app來注冊
依舊采用手動注冊的方式,新建一個springboot項目,項目地址
https://github.com/Ryan-Miao/spring-cloud-demo/tree/master/provider-demo
首先,pom依賴要有eureka
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>provider-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>provider-demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RC2</spring-cloud.version>
<spring-boot-admin.version>2.0.0</spring-boot-admin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-dependencies</artifactId>
<version>${spring-boot-admin.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>central</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<name>aliyun</name>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
注意,配置了eureka,用來注冊。
依賴springfox-swagger2用來展示API。
spring-boot-admin-starter-client才是主動注冊的核心庫,用來發送注冊申請。
需要再次強調了是build
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
這里是為了生成版本信息,提供給spring-boot-admin展示。
provider-demo的配置文件
eureka:
instance:
leaseRenewalIntervalInSeconds: 10
health-check-url-path: /actuator/health
client:
registryFetchIntervalSeconds: 5
serviceUrl:
defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
server:
port: 8082
spring:
application:
name: provider-demo
boot:
admin:
client:
url: "http://localhost:8081"
password: password
username: user
instance:
prefer-ip: true
eureka的配置和admin-server相同,畢竟都是eureka的client嘛。不同的是這里沒有開啟spting security,所以不添加用戶名和密碼信息到meta-data里。
actuator同樣需要暴露全部。
關於spring-boot-admin-client的注冊配置里多了username和password,這個不是自己的,而是admin-server設置的,即前文的里的。
啟動后就可以看到前面的詳細信息了。
巨變在這里
在1.5版本里,我們只要加上eureka注冊,就可以admin-server自動發現所有的app並自己注冊監控了。但這里居然行不通了。我調試了幾個小時,把依賴包翻來覆去研究了好多遍----就是不行!!!
無奈,只好去github把spring-boot-admin的源碼下載下來,找到注冊的代碼開始追蹤。我發現,根本沒有提供任何和eureka注冊中心相關的代碼。看到了spring-boot-admin-server-cloud, 進去看了源碼,這里有關於注冊中心的監聽代碼,也就是admin自動發現app的密碼所在。那我把這個加入dependency不就好了嗎,太年輕。加上后發現找不到版本。我說不應該啊,我有導入dependencyManagement的pom啊。手動指定版本也不行。最后無奈的發現,原來根本沒有發布!!!
⚠️Note: Since Spring Cloud Finchley is not released yet, this version doesn't include Spring Cloud Discovery support
所以,手動注冊吧,騷年。不然你再等等。
結語
通過這一下午的嘗試,追蹤源碼,我發現自己確實挺樂在其中的。然而,這花費了大量的時間和精力。所以,我花費了更多的時間一定要把這次經歷記錄下來,也就是本文了。想說的是,最新的版本果然是坑巨多,慎入!!!如果是作為生產環境的選型,必須跳過這樣的版本。當然,如果是自己個人研究,看新的沒錯。
那么,我到底應不應該學習2.0呢,畢竟1.5也沒學完呢。
學吧,按2.0的學習,工作中還是用1.5. 嗯,就這樣吧。
Miao語
沒有解決不了的bug,只要你用心研究,都可以解決。