微服務註冊與發現
4.1. 服務註冊與發現簡介
服務發現組件的功能
1)服務註冊表:
服務註冊表是一個記錄當前可用服務實例的網絡信息的數據庫,是服務發現機制的核心。服務註冊表提供查詢API和管理API,使用查詢API得到可用的服務實例,使用管理API實現註冊和註銷;html
2)服務註冊
服務註冊很好理解,就是服務啓動時,將服務的網絡地址註冊到服務註冊表中;java
3)健康檢查
服務發現組件會經過一些機制定時檢測已註冊的服務,若是發現某服務沒法訪問了(多是某幾個心跳週期後),就將該服務從服務註冊表中移除。mysql
服務發現:Eureka客戶端
服務發現是基於微服務架構的關鍵原則之一。嘗試配置每一個客戶端或某種形式的約定可能很是困難,能夠很是脆弱。git
Netflix服務發現服務器和客戶端是Eureka。能夠將服務器配置和部署爲高可用性,每一個服務器將註冊服務的狀態複製到其餘服務器。github
註冊Eureka
當客戶端註冊Eureka時,它提供關於自身的元數據,例如主機和端口,健康指示符URL,主頁等。web
Eureka從屬於服務的每一個實例接收心跳消息。若是心跳失敗超過可配置的時間表,則一般將該實例從註冊表中刪除。正則表達式
如何包含Eureka客戶端
要在您的項目中包含Eureka客戶端,請使用組org.springframework.cloud
和工件ID spring-cloud-starter-eureka
的啓動器。算法
有關 使用當前的Spring Cloud發佈列表設置構建系統的詳細信息,請參閱Spring Cloud項目頁面。spring
服務發現方式參看地址:http://www.cnblogs.com/bjlhx/p/8796241.htmlsql
4.2. Eureka簡介
Eureka是Netflix開發的服務發現框架,自己是一個基於REST的服務,主要用於定位運行在AWS域中的中間層服務,以達到負載均衡和中間層服務故障轉移的目的。
Spring Cloud將它集成在其子項目spring-cloud-netflix中,以實現Spring Cloud的服務發現功能。
Eureka 項目2.0將會帶來更好的擴展性,而且使用細粒度的訂閱模型取代了基於拉取的模型
git地址:https://github.com/Netflix/Eureka
4.3. Eureka原理
region和zone(或者Availability Zone)均是AWS的概念。在非AWS環境下,咱們能夠簡單地將region理解爲Eureka集羣,zone理解成機房。這樣可理解下圖——一個Eureka集羣被部署在了zone1機房和zone2機房中。
參看:https://blog.csdn.net/awschina/article/details/17639191
上圖是來自Eureka官方的架構圖,大體描述了Eureka集羣的工做過程。
詳述:
- Application Service 就至關於本書中的服務提供者(用戶微服務),Application Client就至關於本書中的服務消費者(電影微服務);
- Make Remote Call,能夠簡單理解爲調用RESTful的接口;
- us-east-1c、us-east-1d等是zone,它們都屬於us-east-1這個region;
由圖可知,Eureka包含兩個組件:Eureka Server 和 Eureka Client。
Eureka Server提供服務註冊服務,各個節點啓動後,會在Eureka Server中進行註冊,這樣Eureka Server中的服務註冊表中將會存儲全部可用服務節點的信息,服務節點的信息能夠在界面中直觀的看到。
Eureka Client是一個Java客戶端,用於簡化與Eureka Server的交互,客戶端同時也具有一個內置的、使用輪詢(round-robin)負載算法的負載均衡器。
在應用啓動後,將會向Eureka Server發送心跳(默認週期爲30秒)。若是Eureka Server在多個心跳週期內沒有接收到某個節點的心跳,Eureka Server將會從服務註冊表中把這個服務節點移除(默認90秒)。
Eureka Server之間將會經過複製的方式完成數據的同步。(詳見Eureka高可用章節)
Eureka還提供了客戶端緩存的機制,即便全部的Eureka Server都掛掉,客戶端依然能夠利用緩存中的信息消費其餘服務的API。
綜上,Eureka經過心跳檢測、健康檢查、客戶端緩存等機制,確保了系統的高可用性、靈活性和可伸縮性。
4.4. 編寫Eureka Server
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.didispace</groupId>
<artifactId>eureka-server</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>eureka-server</name>
<description>Spring Cloud In Action</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-actuator</artifactId>-->
<!--</dependency>-->
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置類
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka
啓動類
package com.didispace;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class Applicationeureka {
public static void main(String[] args) {
new SpringApplicationBuilder(Applicationeureka.class).web(true).run(args);
}
}
4.5. 將微服務註冊到Eureka Server上
import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; /** * 在這裏咱們使用@SpringBootApplication指定這是一個 spring boot的應用程序. * @author Angel -- 守護天使 * @version v.0.1 * @date 2016年12月10日 */ @SpringBootApplication @EnableEurekaClient @MapperScan("com.itmuch.cloud.*")//掃描:該包下相應的class,主要是MyBatis的持久化類. public class App{ public static void main(String[] args) { SpringApplication.run(App.class, args); } }
git代碼:https://gitee.com/cyj930307/springcloud_textbook.git
4.6. Eureka Server的高可用
4.7. 爲Eureka Server添加用戶認證
在pom.xml中添加spring-boot-starter-seurity的依賴,該依賴爲Eureka Server提供用戶認證的能力。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
在application.yml中添加認證配置。如何不進行配置,則默認用戶名是 user ,默認密碼是一個隨機值,會在項目啓動時打印出來
server: port: 8761 security: basic: enabled: true user: name: root password: 123456 eureka: client: register-with-eureka: false fetch-registry: false service-url: defaultZone: http://root:123456@localhost:8761/eureka
啓動項目,訪問 http://localhost:8761/ 便可看見身份驗證的對話框,輸出設置的用戶名和密碼便可進入。
4.8. 理解Eureka的元數據
Eureka的元數據有兩種:標準元數據和自定義元數據。
標準元數據:主機名、IP地址、端口號、狀態頁和健康檢查等信息,這些信息都會被髮布在服務註冊表中,用於服務之間的調用。
自定義元數據:可使用eureka.instance.metadata-map配置,這些元數據能夠在遠程客戶端中訪問,可是通常不改變客戶端行爲,除非客戶端知道該元數據的含義。
1.客服端修改
server: port: 7900 eureka: client: serviceUrl: defaultZone: http://root:123456@localhost:8761/eureka/ instance: prefer-ip-address: true metadata-map: my-metadata: CYJ spring: datasource: url: jdbc:mysql://localhost:3306/cyj?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=UTC username : root password : 123456 driverClassName : com.mysql.jdbc.Driver max-active: 20 max-idle: 8 min-idle: 8 initial-size: 10 mybatis: mapper-locations: classpath*:mybatis/*Mapper.xml type-aliases-package: com.itmuch.cloud.mybatis.entity
2. 訪問http://localhost:8761/eureka/apps
4.9. Eureka Server的REST端點
Eureka Server提供了一些REST端點。
非JVM的微服務可以使用這些REST端點操做Eureka,從而實現註冊和發現。
事實上,Eureka Client就是一個使用Java編寫的、操做這些REST端點的類庫。
也可分析這些REST端點,編寫其餘語言的Eureka Client。
Eureka提供的REST端點,可使用XML或者JSON與這些端點通訊,默認是XML。
4.10. Eureka的自我保護模式
Eureka的自我保護模式
進入自我保護模式最直觀的體現就是Eureka Server首頁的警告,以下圖:
默認狀況下,若是Eureka Server在必定時間內沒有接收到某個微服務實例的心跳,Eureka Server將會註銷該實例(默認90秒)。可是當網絡分區故障發生時,微服務與Eureka Server之間沒法正常通訊,這就可能變得很是危險了----由於微服務自己是健康的,此時本不該該註銷這個微服務。
Eureka Server經過「自我保護模式」來解決這個問題----當Eureka Server節點在短期內丟失過多客戶端時(可能發生了網絡分區故障),那麼這個節點就會進入自我保護模式。一旦進入該模式,Eureka Server就會保護服務註冊表中的信息,再也不刪除服務註冊表中的數據(也就是不會註銷任何微服務)。當網絡故障恢復後,該Eureka Server節點會自動退出自我保護模式。
自我保護模式是一種對網絡異常的安全保護措施。使用自我保護模式,而已讓Eureka集羣更加的健壯、穩定。
在Spring Cloud中,可使用eureka.server.enable-self-preservation=false來禁用自我保護模式
4.11. 多網卡環境下的IP選擇
簡述:
指定IP在某些場景下頗有用,如某臺服務器有eth0、eth1和eth2三塊網卡,可是eth1能夠被其它的服務器訪問;
若是Eureka Client將eth0或者eth2註冊到Eureka Server上,其它微服務就沒法經過這個IP調用該微服務的接口。
Spring Cloud提供了按需選擇IP的能力,從而避免以上的問題。
操做:
方案一、忽略指定名稱的網卡
#忽略eth0,支持正則表達式
spring.cloud.inetutils.ignored-interfaces[0]=eth0
#註冊時使用ip而不是主機名
eureka.instance.prefer-ip-address=true
方案二、只使用站點本地地址
#只使用站點本地地址
spring.cloud.inetutils.use-only-site-local-interfaces=true
#註冊時使用ip而不是主機名
eureka.instance.prefer-ip-address=true
方案三、手動指定IP地址
#手動指定IP地址
spring.cloud.inetutils.default-ip-address=127.0.0.1
#註冊時使用ip而不是主機名
eureka.instance.prefer-ip-address=true
4.12. Eureka的健康檢查
Eureka的健康檢查
先看下圖:
說明:在Status欄顯示着UP,表示應用程序狀態正常。其它取值DOWN、OUT_OF_SERVICE、UNKNOWN等,只有UP的微服務會被請求。
因爲Eureka Server與Eureka Client之間使用心跳機制來肯定Eureka Client的狀態,默認狀況下,
服務器端與客戶端的心跳保持正常,應用程序就會始終保持「UP」狀態,因此微服務的UP並不能徹底反應應用程序的狀態。
Spring Boot Actuator提供了/health端點,該端點可展現應用程序的健康信息,只有將該端點中的健康狀態傳播到Eureka Server就能夠了,實現這點很簡單,只需爲微服務配置以下內容:
1
2
|
#開啓健康檢查(須要spring-boot-starter-actuator依賴)
eureka.client.healthcheck.enabled = true
|