五、Spring Cloud之網關服務 zuul

前言

問:什麼是網關服務?
答:給外部提供單一的訪問接口,並做過濾和攔截處理的服務。

問:微服務架構中網關服務有什麼作用?
答:我們微服務架構中項目衆多,如果直接拋給外部,將會很容易引起調用錯誤並且大大增加了維護成本,所以我們需要提供單一訪問接口,外部請求全部通過統一端口網關,然後在分發到不同的服務器。如果熟悉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,大數據等。資料包含視頻文檔以及源碼,同時分享本人及投遞的優質技術博文。

如果大家喜歡記得關注和分享喲❤

file

閱讀原文

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章