註冊中心環境搭建
Maven依賴資訊
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <!-- 管理依賴 --> <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> <dependencies> <!--SpringCloud eureka-server --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> <!-- 注意: 這裡必須要新增, 否者各種依賴有問題 --> <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>
application.yml
###服務埠號 server: port: 8100 ###eureka 基本資訊配置 eureka: instance: ###註冊到eurekaip地址 hostname: 127.0.0.1 client: serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ ###因為自己是為註冊中心,不需要自己註冊自己 register-with-eureka: false ###因為自己是為註冊中心,不需要檢索服務 fetch-registry: false
啟動Eureka服務
@EnableEurekaServer @SpringBootApplication public class AppEureka { public static void main(String[] args) { SpringApplication.run(AppEureka.class, args); } }
註冊服務提供者
Maven依賴資訊
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <!-- 管理依賴 --> <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> <dependencies> <!-- SpringBoot整合Web元件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- SpringBoot整合eureka客戶端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <!-- 注意: 這裡必須要新增, 否者各種依賴有問題 --> <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>
application.yml
###服務啟動埠號 server: port: 8000 ###服務名稱(服務註冊到eureka名稱) spring: application: name: app-itmayiedu-member ###服務註冊到eureka地址 eureka: client: service-url: defaultZone: http://localhost:8100/eureka ###因為該應用為註冊中心,不會註冊自己 register-with-eureka: true ###是否需要從eureka上獲取註冊資訊 fetch-registry: true
服務介面
@RestController public class MemberController { @RequestMapping("/getMember") public String getMember() { return "this is getMember"; } }
啟動會員服務
@SpringBootApplication @EnableEurekaClient public class AppMember { public static void main(String[] args) { SpringApplication.run(AppMember.class, args); } }
服務消費者
Maven依賴資訊
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <!-- 管理依賴 --> <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> <dependencies> <!-- SpringBoot整合Web元件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- SpringBoot整合eureka客戶端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <!-- 注意: 這裡必須要新增, 否者各種依賴有問題 --> <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>
Application.yml配置
###服務啟動埠號 server: port: 8001 ###服務名稱(服務註冊到eureka名稱) spring: application: name: app-itmayiedu-order ###服務註冊到eureka地址 eureka: client: service-url: defaultZone: http://localhost:8100/eureka ###因為該應用為註冊中心,不會註冊自己 register-with-eureka: true ###是否需要從eureka上獲取註冊資訊 fetch-registry: true
使用rest方式呼叫服務
@RestController public class OrderController { @Autowired private RestTemplate restTemplate; @RequestMapping("/getorder") public String getOrder() { // order 使用rpc 遠端呼叫技術 呼叫 會員服務 String memberUrl = "http://app-itmayiedu-member/getMember"; String result = restTemplate.getForObject(memberUrl, String.class); System.out.println("會員服務呼叫訂單服務,result:" + result); return result; } }
啟動消費者服務
@SpringBootApplication @EnableEurekaClient public class AppOrder { public static void main(String[] args) { SpringApplication.run(AppOrder.class, args); } @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } }
@LoadBalanced就能讓這個RestTemplate在請求時擁有客戶端負載均衡的能力
高可用註冊中心
在微服務中,註冊中心非常核心,可以實現服務治理,如果一旦註冊出現故障的時候,可能會導致整個微服務無法訪問,在這時候就需要對註冊中心實現高可用叢集模式。
Eureka高可用原理
預設情況下Eureka是讓服務註冊中心,不註冊自己
###註冊自己 register-with-eureka: true ###需要去註冊中心上檢索服務 fetch-registry: true
Eureka高可用實際上將自己作為服務向其他服務註冊中心註冊自己,這樣就可以形成一組相互註冊的服務註冊中心,從而實現服務清單的互相同步,達到高可用效果。
客戶端整合Eureka叢集
server: port: 8000 spring: application: name: app-itmayiedu-member #eureka: # client: # service-url: # defaultZone: http://localhost:8100/eureka ###叢集地址 eureka: client: service-url: defaultZone: http://localhost:8100/eureka,http://localhost:8200/eureka register-with-eureka: true fetch-registry: true
Eureka詳解
服務消費者模式
獲取服務
消費者啟動的時候,使用服務別名,會傳送一個rest請求到服務註冊中心獲取對應的服務資訊,讓後會快取到本地jvm客戶端中,同時客戶端每隔30秒從伺服器上更新一次。
可以通過 fetch-inte vall-seconds=30引數進行修以通過eureka.client .registry該引數預設值為30, 單位為秒。
服務下線
在系統執行過程中必然會面臨關閉或重啟服務的某個例項的情況,在服務關閉期有我們自然不希望客戶端會繼續呼叫關閉了的例項。所以在客戶端程式中,當服務例項過正常的關閉操作時,它會觸發一個服務下線的REST請求給Eureka Server, 告訴服務日中心:“我要下線了”。服務端在接收到請求之後,將該服務狀態置為下線(DOWN),井該下線事件傳播出去。
服務註冊模式
失效剔除
有些時候,我們的服務例項並不一定會正常下線,可能由於記憶體溢位、網路故障氣因使得服務不能正常工作,而服務註冊中心並未收到“服務下線”的請求。為了從服務表中將這些無法提供服務的例項剔除,Eureka Server 在啟動的時候會建立一個定時任多預設每隔一一段時間(預設為60秒)將當前清單中超時(預設為90秒)沒有續約的服務除出去
自我保護
預設情況下,EurekaClient會定時向EurekaServer端傳送心跳,如果EurekaServer在一定時間內沒有收到EurekaClient傳送的心跳,便會把該例項從註冊服務列表中剔除(預設是90秒),但是在短時間內丟失大量的例項心跳,這時候EurekaServer會開啟自我保護機制,Eureka不會踢出該服務。
產生的原因:
在開發測試時,需要頻繁地重啟微服務例項,但是我們很少會把eureka server一起重啟(因為在開發過程中不會修改eureka註冊中心),當一分鐘內收到的心跳數大量減少時,會觸發該保護機制。可以在eureka管理介面看到Renews threshold和Renews(last min),當後者(最後一分鐘收到的心跳數)小於前者(心跳閾值)的時候,觸發保護機制,會出現紅色的警告:
EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT.RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEGING EXPIRED JUST TO BE SAFE. |
從警告中可以看到,eureka認為雖然收不到例項的心跳,但它認為例項還是健康的,eureka會保護這些例項,不會把它們從登錄檔中刪掉。
該保護機制的目的是避免網路連線故障,在發生網路故障時,微服務和註冊中心之間無法正常通訊,但服務本身是健康的,不應該登出該服務,如果eureka因網路故障而把微服務誤刪了,那即使網路恢復了,該微服務也不會重新註冊到eureka server了,因為只有在微服務啟動的時候才會發起註冊請求,後面只會傳送心跳和服務列表請求,這樣的話,該例項雖然是執行著,但永遠不會被其它服務所感知。所以,eureka server在短時間內丟失過多的客戶端心跳時,會進入自我保護模式,該模式下,eureka會保護登錄檔中的資訊,不在登出任何微服務,當網路故障恢復後,eureka會自動退出保護模式。自我保護模式可以讓叢集更加健壯。
但是我們在開發測試階段,需要頻繁地重啟發布,如果觸發了保護機制,則舊的服務例項沒有被刪除,這時請求有可能跑到舊的例項中,而該例項已經關閉了,這就導致請求錯誤,影響開發測試。所以,在開發測試階段,我們可以把自我保護模式關閉,只需在eureka server配置檔案中加上如下配置即可:
但在生產環境,不會頻繁重啟,所以,一定要把自我保護機制開啟,否則網路一旦終端,就無法恢復。
當然關於自我保護還有很多個性化配置,這裡不詳細說明。
注意考慮網路不可達情況下:呼叫介面冪等、重試、補償等。
關閉服務保護
Eureka伺服器端配置
###服務埠號 server: port: 8100 ##定義服務名稱 spring: application: name: app-itmayiedu-eureka eureka: instance: ###註冊中心ip地址 hostname: 127.0.0.1 client: serviceUrl: ##註冊地址 defaultZone: http://${eureka.instance.hostname}:8100/eureka/ ####因為自己是註冊中心,是否需要將自己註冊給自己的註冊中心(叢集的時候是需要是為true) register-with-eureka: false ###因為自己是註冊中心, 不需要去檢索服務資訊 fetch-registry: false server: # 測試時關閉自我保護機制,保證不可用服務及時踢出 enable-self-preservation: false eviction-interval-timer-in-ms: 2000
Eureka客戶端配置
###訂單服務的埠號 server: port: 8001 ###服務別名----服務註冊到註冊中心名稱 spring: application: name: app-itmayiedu-order eureka: client: service-url: ##### 當前會員服務註冊到eureka服務地址 # defaultZone: http://localhost:8100/eureka,http://localhost:9100/eureka defaultZone: http://localhost:8100/eureka ### 需要將我的服務註冊到eureka上 register-with-eureka: true ####需要檢索服務 fetch-registry: true registry-fetch-interval-seconds: 30 # 心跳檢測檢測與續約時間 # 測試時將值設定設定小些,保證服務關閉後註冊中心能及時踢出服務 instance: ###Eureka客戶端向服務端傳送心跳的時間間隔,單位為秒(客戶端告訴服務端自己會按照該規則) lease-renewal-interval-in-seconds: 1 ####Eureka服務端在收到最後一次心跳之後等待的時間上限,單位為秒,超過則剔除(客戶端告訴服務端按照此規則等待自己) lease-expiration-duration-in-seconds: 2
宣告式服務呼叫SpringCloud Feign 主流
feign介紹
Feign客戶端是一個web宣告式http遠端呼叫工具,提供了介面和註解方式進行呼叫。
環境搭建
Maven依賴資訊
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
feign客戶端介面
// name 指定服務名稱 @FeignClient(name = "app-itmayiedu-member") public interface MemberApifeign { @RequestMapping("/getMember") public String getMember(); }
controller
@Autowired private MemberApifeign memberApifeign; @RequestMapping("/feignMember") public String feignMember() { return memberApifeign.getMember(); }
專案啟動加上@EnableFeignClients
@SpringBootApplication @EnableEurekaClient @EnableFeignClients public class AppOrder { public static void main(String[] args) { SpringApplication.run(AppOrder.class, args); }
Ribbon配置
SpringCloud Feign客戶端Http呼叫工具,預設已經整合了Ribbon負載均衡客戶端。
配置Feign客戶端超時時間
###設定feign客戶端超時時間 ribbon: ###指的是建立連線所用的時間,適用於網路狀況正常的情況下,兩端連線所用的時間。 ReadTimeout: 5000 ###指的是建立連線後從伺服器讀取到可用資源所用的時間。 ConnectTimeout: 5000
@RestController publicclass OrderController { @Autowired private RestTemplate restTemplate;
@RequestMapping("/getorder") public String getOrder() { // order 使用rpc遠端呼叫技術 呼叫 會員服務 String memberUrl = "http://app-itmayiedu-member/getMember"; String result = restTemplate.getForObject(memberUrl, String.class); System.out.println("會員服務呼叫訂單服務,result:" + result); returnresult; }
}
|