Spring Cloud Eureka
項(xiàng)目實(shí)例以及文章參考: http://cxytiandi.com/blog/detail/17470
GitHub: https://github.com/hanmosi/tay-spring-cloud/tree/master/chentay-eureka
Eureka介紹
Spring Cloud Eureka是Spring Cloud Netflix項(xiàng)目下的服務(wù)治理模塊。
而Spring Cloud Netflix項(xiàng)目是Spring Cloud的子項(xiàng)目之一麦备,主要內(nèi)容是
對(duì)Netflix公司一系列開源產(chǎn)品的包裝漱逸,它為Spring Boot應(yīng)用提供了自配置的
Netflix OSS整合凡恍。通過(guò)一些簡(jiǎn)單的注解锐极,開發(fā)者就可以快速的在應(yīng)用中配置一
下常用模塊并構(gòu)建龐大的分布式系統(tǒng)。它主要提供的模塊包括:服務(wù)發(fā)現(xiàn)(Eureka)收捣,
斷路器(Hystrix)缀辩,智能路由(Zuul),客戶端負(fù)載均衡(Ribbon)等弱睦。
配置服務(wù)注冊(cè)中心百姓,好處在于,我們不需要知道究竟有多少服務(wù)供我們使用况木,只需要關(guān)注服務(wù)注冊(cè)中心
是否存在我們想要使用的服務(wù)垒拢。即,當(dāng)我們需要調(diào)用某一個(gè)服務(wù)的時(shí)候火惊,首先會(huì)到Eureka中去拉取服務(wù)
列表子库,如果存在對(duì)應(yīng)的服務(wù),則獲取對(duì)應(yīng)的信息進(jìn)行相應(yīng)的調(diào)用請(qǐng)求矗晃。
Spring Cloud中使用Eureka
注意:這里使用Gradle來(lái)進(jìn)行項(xiàng)目管理(有需要的同學(xué)仑嗅,可以自行了解Gradle的使用),因此首先創(chuàng)建一個(gè)Gradle項(xiàng)目
- 在build.gradle中添加對(duì)應(yīng)的依賴包
buildscript {
ext {
springBootVersion = '2.0.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'org.tay.chen'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
maven { url "https://repo.spring.io/milestone" }
}
ext {
springCloudVersion = 'Finchley.M9'
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server')
runtime('org.springframework.boot:spring-boot-devtools')
compileOnly('org.projectlombok:lombok')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
- 接著在啟動(dòng)類中使用@EnableEurekaServer注解张症,使之成為EurekaServer(服務(wù)注冊(cè)中心)
/**
* 服務(wù)注冊(cè)中心
*
* @author chentai
* @since 2018/03/23
*/
@EnableEurekaServer
@SpringBootApplication
public class ChentayEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(ChentayEurekaApplication.class, args);
}
}
- 最后編寫配置文件application.yml(這里推薦使用yaml配置)
server:
port: 8761
spring:
application:
name: chentay-eureka
eureka:
instance:
hostname: localhost
# 作為服務(wù)注冊(cè)中心仓技,不需要向注冊(cè)中心注冊(cè)發(fā)現(xiàn)自己,所以設(shè)置為false
client:
register-with-eureka: false
# 由于注冊(cè)中心的職責(zé)就是維護(hù)服務(wù)實(shí)例俗他,它并不需要去檢索服務(wù)脖捻,所以也設(shè)置為false
fetch-registry: false
server:
enable-self-preservation: true # 關(guān)閉自我保護(hù)
最后運(yùn)行啟動(dòng)類,訪問(wèn) http://localhost:8761 就可以打開Eureka管理頁(yè)面了兆衅。
至此地沮,一個(gè)簡(jiǎn)單的Eureka(服務(wù)注冊(cè)中心)應(yīng)用便搭建成功了嗜浮。
Eureka增加權(quán)限認(rèn)證
上面我們簡(jiǎn)單的介紹了下注冊(cè)中心Eureka,文章地址:https://github.com/hanmosi/tay-spring-cloud/blob/master/chentay-eureka/eureka.md
Eureka自帶了一個(gè)web的管理頁(yè)面摩疑,方便我們查詢注冊(cè)到上面的實(shí)例信息危融,但是有一個(gè)問(wèn)題是如果這個(gè)地址有公網(wǎng)IP的話,必然能直接訪問(wèn)到雷袋,這樣是不安全的吉殃。
如何解決這個(gè)問(wèn)題呢?加用戶認(rèn)證即可楷怒!通過(guò)spring-security來(lái)開始用戶認(rèn)證蛋勺。
- 在build.gradle中添加spring-security的依賴包
dependencies {
compile('org.springframework.boot:spring-boot-starter-security')
}
注意,本實(shí)例的Spring Cloud項(xiàng)目是基于Spring Boot 2.0建立的鸠删,其中Spring Boot 2.0之前一些舊的配置已經(jīng)不推薦使用抱完,并且使用之后無(wú)效。
- 比如在這之前刃泡,我們添加spring-security依賴之后乾蛤,可以直接在yaml文件里面配置一下內(nèi)容即可
# 增加權(quán)限認(rèn)證
security:
basic:
enabled: true
user:
name: chentay
password: chentay
- 當(dāng)然在Spring Boot 2.0之前的版本還需要注意一點(diǎn),就是配置了用戶密碼之后捅僵,項(xiàng)目中的注冊(cè)中心地址的配置也需要改變,需要加上認(rèn)證的用戶名和密碼家卖。
eureka:
client:
service-url:
defaultZone: http://chentay:chentay@localhost:8761/eureka/
- 此時(shí)配置完成,重啟服務(wù)庙楚,不出意外上荡,我們可以通過(guò)配置好的用戶密碼進(jìn)行訪問(wèn)服務(wù)注冊(cè)管理頁(yè)面。但是不幸的是馒闷,Spring Boot 2.0已經(jīng)不推薦使用這樣的操作酪捡,并且,security認(rèn)證的密碼信息必須經(jīng)過(guò)加密纳账,否則不予通過(guò)逛薇。因此,想要對(duì)我們的eureka服務(wù)進(jìn)行簡(jiǎn)單的權(quán)限控制疏虫,就必須通過(guò)WebSecurityConfigurerAdapter 來(lái)進(jìn)行簡(jiǎn)單的認(rèn)證配置了永罚。有需要的同學(xué)可以自行了解Spring Security。
/**
* 權(quán)限過(guò)濾認(rèn)證
*
* @author chentai
* @since 2018/03/24
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("chentay").password(passwordEncoder().encode("chentay")).roles("ADMIN");
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
}
}
從代碼可以看出卧秘,我們使用了@Configuration呢袱、@EnableWebSecurity兩個(gè)注解,將我們的類注入到配置里面翅敌,同時(shí)開啟安全認(rèn)證羞福。這里值得注意的是,必須對(duì)密碼進(jìn)行加密處理蚯涮。
至此治专,我們的安全認(rèn)證已經(jīng)配置完成卖陵,重啟服務(wù),輸入我們?cè)O(shè)置的用戶密碼张峰,OK泪蔫,能夠成功訪問(wèn)!
Eureka 服務(wù)上下線監(jiān)控
如果僅僅是本地調(diào)試挟炬,我們不需要監(jiān)控服務(wù)的上下線。但是嗦哆,生產(chǎn)環(huán)境中谤祖,我們的微服務(wù)模塊絕不僅僅只有那么幾個(gè),可能存在的微服務(wù)會(huì)很多老速。
這時(shí)候我們總不能安排一個(gè)人實(shí)時(shí)查看Eureka服務(wù)列表粥喜,此時(shí),我們有必要對(duì)我們的服務(wù)的上下線進(jìn)行監(jiān)控橘券。
在Eureka服務(wù)中進(jìn)行檢測(cè)通知额湘,Eureka中提供了事件監(jiān)聽的方式來(lái)支持?jǐn)U展
EurekaInstanceCanceledEvent 服務(wù)下線事件
EurekaInstanceRegisteredEvent 服務(wù)注冊(cè)事件
EurekaInstanceRenewedEvent 服務(wù)續(xù)約事件
EurekaRegistryAvailableEvent Eureka注冊(cè)中心啟動(dòng)事件
EurekaServerStartedEvent Eureka Server啟動(dòng)事件
/**
* Eureka事件監(jiān)控
*
* @author chentai
* @since 2018/03/24
*/
@Slf4j
@Component
public class EurekaStateChangeListener {
@Autowired
private DateFormatUtils dateFormatUtils;
@EventListener
public void listen(EurekaInstanceCanceledEvent event) {
log.error("{}\t{} 服務(wù)下線",event.getServerId(),event.getAppName());
}
@EventListener
public void listen(EurekaInstanceRegisteredEvent event) {
InstanceInfo instanceInfo = event.getInstanceInfo();
log.info("{}進(jìn)行注冊(cè)",instanceInfo.getAppName());
}
@EventListener
public void listen(EurekaInstanceRenewedEvent event) {
log.info("{}\t{} 服務(wù)進(jìn)行續(xù)約",event.getServerId(),event.getAppName());
}
@EventListener
public void listen(EurekaRegistryAvailableEvent event) {
log.info("{} 注冊(cè)中心啟動(dòng)",dateFormatUtils.stampToDate(event.getTimestamp()));
}
@EventListener
public void listen(EurekaServerStartedEvent event) {
log.info("{} Eureka Server 啟動(dòng)",dateFormatUtils.stampToDate(event.getTimestamp()));
}
}
這里只是演示事件的效果,具體在什么事件中需要做什么操作旁舰,需要發(fā)郵件還是發(fā)短信锋华,需要大家按自己的需求去實(shí)現(xiàn)了。
注意:在Eureka集群環(huán)境下箭窜,每個(gè)節(jié)點(diǎn)都會(huì)觸發(fā)事件毯焕,這個(gè)時(shí)候需要控制下發(fā)送通知的行為,不控制的話每個(gè)節(jié)點(diǎn)都會(huì)發(fā)送通知磺樱。