前言
問:什麼是網關服務?
答:給外部提供單一的訪問接口,並做過濾和攔截處理的服務。
問:微服務架構中網關服務有什麼作用?
答:我們微服務架構中項目衆多,如果直接拋給外部,將會很容易引起調用錯誤並且大大增加了維護成本,所以我們需要提供單一訪問接口,外部請求全部通過統一端口網關,然後在分發到不同的服務器。如果熟悉nginx 的同學想必就知道,其實就是nginx 反向代理的功能。
問:那爲什麼不使用nginx,而是使用zuul
答: nginx 確實可以實現網關的功能,但是我們同樣的要維護nginx.conf 文件,如果項目夠多,是很容易出問題的,使用zuul 的話,可以和eureka 天然的融合,使得管理維護起來更加方便。
下面我們就來看下怎麼實現zuul 吧。
pom.xml
我們創建一個zuul 的模塊,pom.xml 文件中引入zuul 和erueka
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
啓動類
在啓動類中我們加入@EnableZuulProxy 註解
將springBootApplication 註解換成@SpringCloudApplication 註解。
EnableZuulProxy 註解表示啓動zuul 網關服務。
SpringCloudApplication 註解,我們來看下源碼
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
可以看到包含的註解主要是SpringBootApplication、EnableDiscoveryClient、EnableCircuitBreaker 而這三個註解,我們前面都接觸過的,SpringBootApplication就是Springboot項目啓動的專用註解,EnableDiscoveryClient註解是將服務註冊到服務中心,並發現服務的。EnableCircuitBreaker 是實現熔斷處理的註解,所以說SpringCloudApplication 註解是對三個的一層封裝,所以我們以後構建微服務的時候,使用SpringCloudApplication 註解會更方便。
application.properties
接下來我們在配置問價中增加如下配置
server.port=9007
spring.application.name=zuul
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
zuul.routes.test-a.path=/a/**
zuul.routes.test-a.service-id=ribbon-consumer
server.port和spring.application.name 用來指定項目啓動的端口和項目在註冊中心的名稱,eureka.client.serviceUrl.defaultZone用來指定註冊中心的地址。
zuul.routes.*.path 和zuul.routes.*.service-id 用來指定我們的目的項目。
比如我這裏配置的ribbon-consumer 項目,將localhost:9007/a/** 轉發到ribbon-consumer 對應的接口上。
測試
好了,我們現在就把網關配置好了。我們現在啓動一下項目,啓動如下幾個項目進行測試吧就。
其中EurekaServer是註冊中心,ribbon-consumer 是服務消費者,ribbon-consumer 是服提供者,zuul 是網關。我們啓動好這幾個項目後,我們輸入一下地址:
http://localhost:9007/a/index
可以看到其實訪問的是
http://localhost:9003/index
默認映射
上面的可以看到,我們主要的配置就是在配置文件中配置好目標地址的路徑。但是這樣的話,和nginx 有什麼區別呢,如果項目足夠多配置起來還是會出錯的,所以前面說zuul 和eureka 可以無縫連接,所以,這裏zuul 做了一個默認映射,爲所有註冊到註冊中心的服務提供了一個唯一對應的默認映射。怎麼說呢,我們看一下服務中心的控制檯。
zuul 將eureka 中服務名作爲映射前綴,比如
http://localhost:9007/ribbon-consumer/index
可以看到,達到了一樣的效果,ribbon-consumer 就是服務名。
請求過濾
前面我們講了zuul 網關可以轉發請求,但是它還有一個強大的功能,那就是請求過濾,我們知道具體項目中我們的接口會做安全限制,所以在具體的項目中會寫過濾器和攔截器。在微服務項目中,我們既然提供了統一的網關服務,所以我們可以將安全校驗和具體業務剝離出來,將安全校驗放在zuul 網關中來統一處理,這樣減少了冗餘代碼,也方便維護。
那麼怎在zuul 中實現請求過濾呢?
繼承ZuulFilter 類。
我們創建一個AccessFilter你類來繼承ZuulFilter 。代碼如下:
@Slf4j
public class AccessFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx=RequestContext.getCurrentContext();
HttpServletRequest request=ctx.getRequest();
String token=request.getParameter("token");
if(token == null || !token.equals("123456")){
log.info("token is error!");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(500);
return "error";
}
log.info("token is ok");
return null;
}
}
直接將書上的解釋拿出來了。主要的方法是run方法,獲取請求中的request 和參數,對參數進行校驗從而過濾。
這裏我就是對token 進行簡單的校驗,也就是說只有檢驗通過了才能訪問目標接口。
昨晚上面這些還不夠,還差一步,在項目zuul 服務啓動的時候,需要將 AccessFilter bean 註冊服務中。所以我們在啓動類中注入
@Bean
public AccessFilter accessFilter(){
return new AccessFilter();
}
好了,我們來啓動一下項目看看。
可以看到就可以起到攔截的作用。
番外
到此爲止,zuul 網關服務搭建好了,並運行一個非常簡單的例子。
代碼上傳到github:
https://github.com/QuellanAn/SpringCloud
後續加油♡
歡迎大家關注個人公衆號 “程序員愛酸奶”
分享各種學習資料,包含java,linux,大數據等。資料包含視頻文檔以及源碼,同時分享本人及投遞的優質技術博文。
如果大家喜歡記得關注和分享喲❤