文章目的
本文提供給正在頭疼服務註冊中心和網關集成的各位朋友;
最近新換的工作,新的環境和新的工作方式,新的工作環境技術經理要求我們自己選用框架,但是他會給我們提供思路,公司準備做一個有多服務模塊的項目,因爲前期劃分不詳細,此處暫時不能稱之爲微服務項目,因爲本人也是第一次接觸微服務開發模式,不免有些手忙腳亂,但是經過一段時間的學習和驗證,有些心得以及經驗,分享給需要的朋友!
文章正文
一、Eureka是什麼,Zuul又是什麼?(What)
1.Eureka(服務註冊中心)
Eureka 是 Netflix 下的服務發現框架,何爲發現,發現在這裏是一個動詞,執行發現操作的服務發現了另外一個可以被發現的服務,既發現者和被發現者,Euerka分爲兩部分:
Euerka Server(發現者) 和 Eureka Client(被發現者);
那麼他們能幹什麼呢?
在Eureka Client正常啓動以後會向Eureka Server按照指定的頻率發送心跳;
在Eureka Server正常啓動以後可以獲取查看所有心跳正常的Euerka Client;
2.Zuul(網關)
Zuul 是 一個API網關,API網關可以提供一個單獨且統一的API入口用於訪問內部一個或多個API。它可以將一個一直的請求通過路由的方式,映射到另外一個地址,使真實地址不可見;也可以對所有的請求進行攔截,驗證,簡單來說嘛就是一個統一入口,比如現在的支付寶或者微信的相關api服務一樣,都有一個統一的api地址,統一的請求參數,統一的鑑權。
這裏只是簡單講一下Euerka是啥東西,因爲我們的重點是使用,如果小夥伴需要詳細瞭解Euerka和Zuul請移步至以下文章:
Euerka詳解&Zuul詳解
二、爲什麼要使用服務註冊中心,爲什麼要使用網關?(Why)
1.服務註冊中心(Eureka)
Eureka是一種基於REST(Representational State Transfer)的服務,主要用於AWS雲,用於定位服務,以實現中間層服務器的負載平衡和故障轉移。我們稱這個服務,Eureka Server。Eureka還提供了一個基於Java的客戶端組件Eureka Client,它使得與服務的交互變得更加容易。客戶端還具有內置負載均衡器,可進行基本的輪詢負載均衡。
通過Eureka Client定期向Eureka Server的發送的心跳,可以判斷Euerka Client的生存狀態,Eureka通過心跳檢查、客戶端緩存等機制,確保了系統的高可用性、靈活性和可伸縮性。
2.網關(Zuul)
Zuul是Netflix開源的微服務網關,可以和Eureka、Ribbon、Hystrix等組件配合使用,Spring Cloud對Zuul進行了整合與增強,Zuul的主要功能是路由轉發和過濾器。
Zuul基於JVM的路由器和服務器端負載均衡器。它的本質是一個過濾器鏈,同時,Zuul的規則引擎允許規則和過濾器基本上用任何JVM語言編寫,內置支持Java和Groovy。這個功能,就可以實現動態路由的功能了。當需要添加某個新的對外服務時,一般上不停機更新是通過數據緩存配置或者使用Groovy進行動態路由的添加的。
三、怎樣使用服務註冊中心,怎樣使用網關?(How)
1.服務註冊中心(Eureka)
1.首先創建一個springboot項目,基礎結構如下:
2.在pom.xml中引入eureka-server
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
3.在項目啓動類上加上@EnableEurekaServer註解
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
4.將resources下application.properties文件更名爲application.yml,我們配置文件將統一使用yml格式:
server:
port: 8798
spring:
application:
name: eureka-server
eureka:
instance:
hostname: localhost
server:
# 關閉eureka服務器的自我保護功能,忽略網絡分區故障
enable-self-preservation: false
# eureka服務器檢測失效服務的時間間隔
eviction-interval-timer-in-ms: 5000
client:
# eureka服務器本身也是一個客戶端,顧不需要註冊自身
register-with-eureka: false
fetch-registry: false
至此,一個簡單的Eureka Server就搭建成功了,啓動項目,在瀏覽器中打開:
出現此頁面說明Euerka啓動成功,途中紅字部分,是提示EuerkaServer關閉了自我保護功能
2.網關(Zuul)
1.同樣,創建一個springboot項目,結構如下:
其中:
Constants包中放的是一個類,類中存放的是全局靜態枚舉
Filter中存放的是Zuul的四大核心過濾器 pre rout post error ;demo中有完整的說明以及詳細步驟
rule中存放的是Zuul的配置類,用於自定義負載均衡策略
2.在pom.xml中添加 eureka-client依賴 和 zuul 依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
3.在項目啓動類上加上@EnableEurekaClient 和 @EnableZuulProxy註解
@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
4.將resources下application.properties文件更名爲application.yml:
server:
port: 8086
spring:
application:
name: zuul-server
eureka:
client:
service-url:
defaultZone: http://localhost:8798/eureka/
# 表示eureka client間隔多久去拉取服務註冊信息
registry-fetch-interval-seconds: 5
instance:
instance_id: ${spring.cloud.client.hostname}:${server.port}:${spring.application.name}:@project.version@
demo中有詳細的網關路由,映射,屏蔽,負載的配置
至此,一個簡單的 Zuul 網關就 以 Eureka Client 的形式搭建成功了,啓動項目,在瀏覽器中查看剛剛的Eureka管理頁面:
圖片中我們看到在application列表中出現了 zuul-server 的服務,這就是我們剛剛搭建的網關微服務,小夥伴們肯定會問我現在搭好了網關,可是怎麼用呢?別急,網關的功能體現是需要其他服務一起運作的,具體的往下看,看ribbon的使用,裏邊有介紹.
3.負載均衡(ribbon)
ribbon,大家都是到負責負載均衡的一個工具,在spring-cloud中,zuul 默認集成了 ribbon ,所謂負載均衡,就是當一個微服務的訪問量在增大時,一個服務器已經支撐不住,這個時候就會在使用一臺服務器部署一個同樣的服務上去,這種情況下,用戶訪問這兩個服務期中的任何一臺服務器中的服務都可以拿到正確結果,負載均衡的作用就是根據你定義的策略或默認策略,去合理的使用這兩個服務器上的相同的服務,達到資源的合理利用,具體體現如何呢,我們往下看,首先,我們需要三個或多個服務提供者(provider)來體現zuul和ribbon的具體功能體現:
1.我們先創建兩個服務提供者,並各自提供一個相同的接口,但返回值不同:
創建一個springboot項目,結構如下:
引入 eureka client 依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
在項目啓動類上加上@EnableEurekaClient註解
@SpringBootApplication
@EnableEurekaClient
public class Provider1stApplication {
public static void main(String[] args) {
SpringApplication.run(Provider1stApplication.class, args);
}
}
將resources下application.properties文件更名爲application.yml:
server:
port: 8081
spring:
application:
name: provider1
eureka:
client:
service-url:
defaultZone: http://localhost:8798/eureka/
instance:
instance_id: ${spring.cloud.client.hostname}:${server.port}
lease-renewal-interval-in-seconds: 5
lease-expiration-duration-in-seconds: 10
在TestController中創建一個對外的接口
@RestController
@RequestMapping("/test1")
public class TestController {
@GetMapping("test1")
public Object test(){
return "123456";
}
}
到此一個服務提供者創建完畢,按照上述的方式修改一下端口和接口返回值,創建第二個服務提供者
application.yml:
server:
port: 8082
spring:
application:
name: provider1 #注意,此處的服務名稱也和provider1保持一致
#eureka配置和provider1一致
TestController
@RestController
@RequestMapping("/test1")
public class TestController {
@GetMapping("test1")
public Object test(){
return "456789";
}
}
啓動兩個服務提供者,查看eureka管理頁面:
這時候我們發現又出現了一個和zuul網關同一級的一個服務,有些小夥伴會問,我們不是啓動了兩個服務嗎?大家看後邊status 列裏面是兩個服務,因爲註冊時我們註冊的服務名都是 provider1 所以 eurekaserver 將這兩個服務解讀成一個服務但有兩個可用地址.
2.我們再創建第三個服務提供者,並提供一個跟其他兩個提供者提供的接口不同的接口,返回值也不同:
創建一個springboot項目,結構如下:
引入 eureka client 依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
在項目啓動類上加上@EnableEurekaClient註解
@SpringBootApplication
@EnableEurekaClient
public class Provider3rdApplication {
public static void main(String[] args) {
SpringApplication.run(Provider3rdApplication.class, args);
}
}
將resources下application.properties文件更名爲application.yml:
server:
port: 8083
spring:
application:
name: provider3
eureka:
client:
service-url:
defaultZone: http://localhost:8798/eureka/
instance:
instance_id: ${spring.cloud.client.hostname}:${server.port}
lease-renewal-interval-in-seconds: 5
lease-expiration-duration-in-seconds: 10
在TestController中創建一個對外的接口
@RestController
@RequestMapping("/test3")
public class TestController {
@GetMapping("test3")
public Object test(){
return "789JQK";
}
}
啓動第三個服務,查看eureka管理頁面:
我們發現多了一個provider3 的服務.
至此,三個服務提供者均已搭建配置完成!
這個時候,我們提到上個問題,網關有什麼用呢?
1.zuul可以將我們的服務進行路由
我們訪問provider3的test3/test3接口,我們之前是需要訪問原始路徑:
http://localhost:8083/test3/test3
現在我們有了zuul網關之後,我們可以這樣,使用zuul的地址以及privider3的服務名對provider3進行訪問:
http://localhost:8086/provider3/test3/test3
這就是一個簡單的路由,當然,zuul還可以在yml配置文件中對路由,別名,映射,負載均衡等進行詳細配置,具體見demo
2.zuul可以將多個服務提供者的服務整合到一個統一的入口
我們訪問provider1的test1/test1接口,我們之前是需要訪問原始路徑:
http://localhost:8081/test1/test1
我們訪問provider2的test1/test1接口,我們之前是需要訪問原始路徑:
http://localhost:8082/test1/test1
可是我們知道,我們建立provider1和provider2的目的主要是要實驗負載均衡的機制,是我們分開訪問的話,就不需要負載均衡了,這時候zuul可以這樣,上文中使用zuul的地址以及privider1的服務名對provider1進行訪問:
http://localhost:8086/provider1/test1/test1
多次訪問查看結果,我們發現,返回值在123456和456789之間來回變動,這就是負載均衡的體現.具體的策略有很多種,也可以自定義,自定義的方法我在demo中有寫!
4.Feign客戶端(feign)
什麼是Feign?他是一個Http客戶端,可以向指定服務發送http請求,我們什麼時候會用到呢,比如一般服務,一個訂單的生成,要訂單服務請求商品服務獲取商品價格,這種情況,客戶端請求的是訂單服務,但訂單服務要請求商品服務獲取到商品的價格來生成訂單,這時候feign就派上用場了,我們將provider3當做訂單服務,provider1當做商品服務,我們修改一下剛剛的provider3的代碼,加上feign的支持:
1.在 pom.xml 中加入feign依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.在啓動類添加 @EnableFeignClients 註解:
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class Provider3rdApplication {
public static void main(String[] args) {
SpringApplication.run(Provider3rdApplication.class, args);
}
}
3.創建一個包 feignClient ,並創建Provider1Client:
@FeignClient(name = "provider1")
public interface Provider1Client {
@GetMapping("test1/test1")
String test1();
}
4.在TestController中添加一個接口 test4:
@RestController
@RequestMapping("/test3")
public class TestController {
@Resource
private Provider1Client provider1Client;
@GetMapping("test3")
public Object test(){
return "789JQK";
}
@GetMapping("test4")
public Object test4(){
String provider1Str = provider1Client.test1();
return "test4" + provider1Str;
}
}
然後重啓provider3服務;並訪問剛剛添加的test4接口:
http://localhost:8086/provider3/test3/test4
我們發現可以使用feign將privider1以對象的方式將需要暴露給provider3的接口以方法的方式調用,且zuul的負載均衡效果依然生效.文章中只有普通的get請求,且無參數,demo中有詳細的說明,get,post patch delete請求,以及參數的各種傳輸方式的使用.
至此本demo完結,希望能幫助到有需要的小夥伴!
完整demo結構目錄如下,項目完整,環境搭建好之後可直接運行:
如有疑問可以隨時諮詢本人,若各位發現錯誤請及時提醒,意麪誤導更多的人,謝謝!
如需下載demo,請移步至:http://www.demodashi.com/demo/16379.html
本文純手打,謝謝支持!