1.什麼是服務注冊與發現

服務注冊與發現元件、服務提供者、服務消費者這三者之間依賴關系
- 每個服務在啟動的時候會将自己的一些資訊(如ip、port、server-name等)注冊到注冊中心,服務發現這個元件會會存儲這些資訊。
- 用戶端調用是從注冊中心根據server-name擷取服務的資訊進行通信操作。當然不是每次都是用戶端都是從注冊中心查詢服務資訊,用戶端它也會緩存這個服務資訊到記憶體中,這樣也減少了注冊中心的壓力,即使注冊中心當機也不影響其它服務之間的調用關系。
本文以Eureka作為注冊中心進行講解,雖然現在eureka已經閉源,但是不影響我們學習。SpringCloud提供了多種服務發現的元件,如Eureka、Consul和ZooKeeper。
2.Eureka介紹
Eureka是Eetflix開源的服務注冊與發現元件。它主要包含Server和Client兩個端。SpringCloud将它內建在子項目SpringCloudNetflix中,進而可以實作服務的注冊與發現功能。
- Application Service:相對于提供者。
- Application Client:相對于消費者。
- Eureka Server提供服務注冊與發現,每個服務啟動都會注冊到Eureka Server。
- Eureka Client相對于Java用戶端。Eureka Client啟動後會每隔30秒向Eureka Server發送心跳包,Eureka Server如果90秒内沒有收到心跳包則會踢出對應服務,這也是Eureka的服務保護機制。
3.SpringCloud整合Eureka Server
3.1 建立一個Eureka-server的 Maven工程,并且添加pom依賴
<?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.lk</groupId>
<artifactId>microservice-discovery-eureka</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<!-- 管理依賴 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 注意: 這裡必須要添加, 否者各種依賴有問題 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
3.2 在Resource目錄建立application.yml檔案
###服務端口号
server:
port: 8761
###eureka 基本資訊配置
eureka:
instance:
###注冊到eureka的ip位址
hostname: 127.0.0.1
client:
serviceUrl:
# 設定與eureka server互動的位址,後續查詢服務都是通過這個位址 這個就是注冊中心位址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
###因為自己是為注冊中心,不需要自己注冊自己
register-with-eureka: false
###因為自己是為注冊中心,不需要檢索服務
fetch-registry: false
3.3 編寫啟動類
package com.lk.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @Auther: lk
* @Date: 2019/5/11 16:00
* @Description:
*/
@SpringBootApplication
//@EnableEurekaServer 表示自己是Eureka Servevr
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
4.将服務注冊到Eureka Server
4.1 建立一個項目名為microservice-provider-user的Maven工程,并且添加pom依賴
<?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.lk</groupId>
<artifactId>microservice-discovery-user</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- 管理依賴 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 注意: 這裡必須要添加, 否者各種依賴有問題 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
4.2 在Resource目錄添加application.yml配置
###服務啟動端口号
server:
port: 9901
###服務名稱(服務注冊到eureka名稱)
spring:
application:
#服務名稱
name: microservice-discovery-user
###服務注冊到eureka位址
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
###因為該應用為注冊中心,不會注冊自己
register-with-eureka: true
###是否需要從eureka上擷取注冊資訊
fetch-registry: true
4.3 編寫啟動類
package com.lk.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @Auther: lk
* @Date: 2019/5/11 16:13
* @Description:
*/
@SpringBootApplication
//@EnableEurekaClient 表示自己是Eureka Client端
@EnableEurekaClient
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
接着我們啟動Eureka Server,浏覽器中服務http://localhost:8761
由圖可知,Eureka Server可以顯示很多資訊,如目前示例的運作狀态、注冊到Eureka Server 上的服務執行個體、常用資訊、執行個體資訊等。但是現在僅僅隻啟動了Eureka Servver端,此時還沒有Eureka Clientd端注冊,是以此時清單為空。
接下來我們啟動microservice-provider-user項目。此時我們在浏覽器中通路http://localhost:8761
此時清單中已經顯示有服務注冊上來,并且我們可以看到server-name、服務個數、服務狀态、服務其他資訊等。
5.使用者認證
在實際項目中,一般會配置使用者認證才能允許通路Eureka Server
5.1 為Eureka Server服務添加使用者認證
在之前的Eureka Server項目的pom檔案引入以下依賴資訊
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
在之前的application.yml檔案添加一下内容,把之前檔案覆寫
###服務端口号
server:
port: 8761
###eureka 基本資訊配置
eureka:
instance:
###注冊到eureka的ip位址
hostname: 127.0.0.1
client:
serviceUrl:
# 設定與eureka server互動的位址,後續查詢服務都是通過這個位址 這個就是注冊中心位址
# 因為加了使用者認證 是以需要格式必須是http://使用者名:密碼@eurekahost:eurekaport/
defaultZone: http://user:[email protected]${eureka.instance.hostname}:${server.port}/eureka/
###因為自己是為注冊中心,不需要自己注冊自己
register-with-eureka: false
###因為自己是為注冊中心,不需要檢索服務
fetch-registry: false
spring:
security:
user:
# 賬号
name: user
# 密碼
password: 666666
接着重新啟動Eureka Server服務,浏覽器輸入http://localhost:8761通路
由于配置了使用者認證,如果沒有登入首先會重定向到login頁面進行登入
這個頁面是security架構自帶的,我們可以看下相關源碼配置
這個類是預設的登入頁面,我們可以點選進去看看
init()方法初始化了一些url,接下來我們看下為什麼沒有登入沒被進行攔截
看到doFilter()方法,這不是servlet裡面的過濾器嗎,這個方法主要就是判斷使用者是否登入了沒,如果登入了則放行,沒有登入的會則進入else,this.generateLoginPageHtml方法則是生成一串html字元串,然後使用流的方式傳回給client端。
由于security架構預設開啟csrf校驗,但是在Eureka Client端注冊到Eureka Server端時,如果沒有帶crsf資訊會報錯,是以我們要禁用csrf校驗。
建立WebSecurityConfig類重寫configure方法
package com.lk.app;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
super.configure(http);
}
}
當我們登入成功之後變可以看到Eureka的ui界面,此時是沒有服務注冊的,因為我把其它服務停止了,而且其它服在注冊到注冊中心也需要進行使用者認證.
5.2 為microservice-provider-user服務配置使用者認證
在application.yml檔案中加入如圖配置
如果不加入使用者認證,在服務注冊的時候一直報Cannot execute request on any known server錯誤。
接下來啟動項目,我們可以看到Eureka Server的UI界面會有服務注冊的資訊