Spring Cloud:多環境配置、註冊中心安全認證、容器宿主機IP註冊
記錄一下搭建 Spring Cloud 過程中踩過的一些坑。寫這篇隨筆時候不知道為什麼想到了看過的一個短片《斷崖》,看的時候真的感受到了女主的絕望和無助。感覺自己就像女主一樣,我在自己技術水平的坑裡努力的爬著,好的是我爬出來了,壞的是外面還有一個更大的坑!!!人生路漫漫,且爬且珍惜!
Spring 版本
- Spring Boot:2.0.0.RELEASE
- Spring Cloud:Finchley.SR2
多環境配置
多配置的切換在開發中真是很常用,能有效提高效率。一些成熟的框架基本都有關於配置切換的解決方案,當然了 Spring Cloud 也不例外!
先看看我的配置檔案結構:
配置檔案通過後綴區分:dev - 開發環境配置,test - 測試環境配置,prod - 生產環境配置。
bootstrap.yml 檔案來配置載入那個配置檔案:
spring:
profiles:
active: dev
spring.profiles.active 配置的就是需要載入的配置檔案,這樣就能通過配置來載入不同的配置檔案。
但是,我們一般都是打包成 jar 包來執行,這樣分別打包還是有點麻煩,所以可以打包一個 jar 包,通過新增啟動引數來載入不同的配置:
java -jar xxx.jar --spring.profiles.active=dev 表示使用開發環境的配置 java -jar xxx.jar --spring.profiles.active=test 表示使用測試環境的配置 java -jar xxx.jar --spring.profiles.active=prod 表示使用生產環境的配置
這裡貼一個我封裝的啟動 jar 包的 shell 指令碼:
#!/bin/bash JARURI=$1 # 第一個引數為jar包絕對路徑 CONFENV=$2 # 第二個引數為配置環境 LOGSDIR=$3 # 第三個引數為日誌目錄 # 判斷檔案是否存在 if [ ! -f "$JARURI" ];then echo "ERROR:File does not exist;" exit 1 fi # 判斷日誌目錄是否存在 if [ ! -d "$LOGSDIR" ];then echo "ERROR:Directory does not exist;" exit 1 fi # 判斷配置環境 ENVARR=("dev" "test" "prod") if echo "${ENVARR[@]}" | grep -w "$CONFENV" &>/dev/null; then : else echo "ERROR:Env does not exist;" exit 1 fi # 啟動 OLD_IFS="$IFS" IFS="/" file_array=($JARURI) IFS="$OLD_IFS" file_array_len=${#file_array[*]} file_name_index=`expr $file_array_len - 1` log_uri=${LOGSDIR%*/}/${file_array[$file_name_index]}_"$CONFENV"_$(date "+%Y_%b_%d_%H_%M_%S_%N").txt java -jar $JARURI > $log_uri --spring.profiles.active=$CONFENV &
註冊中心安全認證
註冊中心的頁面是直接就能訪問的,這肯定不是我們所希望的,所以需要新增安全機制進行保護,這裡需要用到依賴 spring-boot-starter-security
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
配置檔案增加 spring.security.user.name 和 spring.security.user.password 配置,修改註冊中心地址:
eureka:
client:
service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@192.168.1.254:9010/eureka/ # 註冊中心地址
register-with-eureka: false # 是否註冊到註冊中心
fetch-registry: false # 是否拉取服務列表
server:
enable-self-preservation: true # 是否開啟註冊中心保護機制
eviction-interval-timer-in-ms: 60000 # 服務清理間隔,毫秒
instance:
prefer-ip-address: true # 是否使用IP地址廣播服務
lease-renewal-interval-in-seconds: 30 # 服務租約時間,秒
lease-expiration-duration-in-seconds: 90 # 間隔多久時間沒有傳送心跳,認為服務不可用,秒
spring:
# 服務設定
application:
name: server-eureka
# 安全機制
security:
user:
name: eureka
password: 123456
# 服務設定
server:
port: 9010
使用此元件,安全是實現了,訪問註冊中心頁面,需要登入使用者名稱和密碼了,但是問題也出現了,客戶端服務一直註冊不上去。我查詢資料給出的解決方案是禁用 security 的 csrf,下面是處理方案,但是我使用此方案並不生效:
@EnableWebSecurity static class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http);//加這句是為了訪問eureka控制檯和/actuator時能做安全控制 http.csrf().disable(); } }
上面的方案我使用不生效,我使用下面的方案解決的:
package com.microview.servereureka.basic; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.NoOpPasswordEncoder; /** * 註冊中心basic認證 */ @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Value("${spring.security.user.name}") private String username; @Value("${spring.security.user.password}") private String password; @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .passwordEncoder(NoOpPasswordEncoder.getInstance()) .withUser(username).password(password) .authorities("ADMIN"); } @Override protected void configure(HttpSecurity http) throws Exception { http .csrf() .disable() .authorizeRequests() .anyRequest().authenticated() .and() .httpBasic(); } }
容器宿主機IP註冊
由於所有的專案都執行在 Docker 容器中,這就導致客戶端註冊到註冊中心的 IP 地址為容器的虛擬 IP,無法通過外部訪問,這裡的解決方案是構建容器時候設定容器的網路模式為橋接模式。
docker-compose.yml 中配置 network_mode: "bridge"
客戶端配置檔案中相關配置(192.168.1.254 為宿主機IP地址):
eureka: client: service-url: defaultZone: http://eureka:[email protected]:9010/eureka/ instance: instance-id: ${eureka.instance.ip-address}:${server.port} ip-address: 192.168.1.254 prefer-ip-address: true
這樣註冊到註冊中心的IP地址就是宿主機的IP了。
參考資料
https://blog.csdn.net/quanqxj/article/details/80592231
https://github.com/spring-cloud/spring-cloud-netflix/issues/2754
https://www.oschina.net/question/556985_2273961
https://blog.csdn.net/qq_36148847/article/details/79427878