服務網關zuul

微服務網關

在微服務環境下,不同的服務有其不同的網絡地址,若讓客戶端直接與各個微服務通信,客戶端會多次請求不同微服務,存在跨域請求,處理相對複雜。此時我們就需要使用微服務網關。微服務網關介於服務端與客戶端的中間層,所有外部服務請求都會先經過微服務網關,客戶只能跟微服務網關進行交互,無需調用特定微服務接口,使得開發得到簡化。服務網關是在微服務前邊設置一道屏障,請求先到服務網關,網關會對請求進行過慮、校驗、路由等處理。有了服務網關可以提高微服務的安全性,網關校驗請求的合法性,請求不合法將被攔截,拒絕訪問。


Zuul簡介

Spring Cloud Zuul是整合Netflix公司的Zuul開源項目實現的微服務網關,它的核心是一組過濾器,它實現了請求路由、負載均衡、校驗過慮等 功能。

 

 

 

zuul與nginx整合使用 

nginx: 負載均衡,反向代理

zuul:  攔截非法請求,保證請求的合法性,負載均衡

 

下面是網上找的一張圖

 

 

 

搭建網關工程

 

pom依賴

    <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>

 

因爲zuul網關需要獲取微服務地址,所以添加了eureka-client的依賴

 

在application啓動類上添加註解,標記此服務是一個網關

@EnableZuulProxy//此工程是一個zuul網關

 

 

 

在   application.yml 文件中配置 eureka

eureka:
  client:
    registerWithEureka: true #服務註冊開關
    fetchRegistry: true #服務發現開關
    serviceUrl: #Eureka客戶端與Eureka服務端進行交互的地址,多箇中間用逗號分隔
      defaultZone: http://localhost:50101/eureka/
  instance:
    prefer-ip-address:  true  #將自己的ip地址註冊到Eureka服務中
    ip-address: 127.0.0.1
    instance-id: zuul50201 #指定實例id
ribbon:
  MaxAutoRetries: 2 #最大重試次數,當Eureka中可以找到服務,但是服務連不上時將會重試,如果eureka中找不到服務則直接走斷路器
  MaxAutoRetriesNextServer: 3 #切換實例的重試次數
  OkToRetryOnAllOperations: false  #對所有操作請求都進行重試,如果是get則可以,如果是post,put等操作沒有實現冪等的情況下是很危險的,所以設置爲false
  ConnectTimeout: 5000  #請求連接的超時時間
  ReadTimeout: 6000 #請求處理的超時時間

 

 

zuul具有代理的功能,將請求轉發給服務

 

配置路由:           application.yml配置

配置zuul網關根路徑   /api  和端口

server:
  port: 50201
  servlet:
    context-path: /api

 

配置路由

zuul:
  routes:
    manager-test1:                        #路由名稱,名稱任意,保持所有路由名稱唯
      path: /test1/**                         #路徑匹配規則,如果不匹配,不會轉發請求
      serviceId:  xc-service-manage-test1    #服務id,從Eureka中找到服務的ip和端口
      #url: http://localhost:31200 #也可指定url,不用 serviceId
      strip-prefix: false   #true:代理轉發時去掉前綴,false:代理轉發時不去掉前綴 /test/是前綴,
      sensitiveHeaders:  #默認zuul會屏蔽cookie,cookie不會傳到下游服務,這裏設置爲空則取消默認的黑名單,如果設置了具體的頭信息則不會傳到下游服務
      ignoredHeaders:  #可以設置過慮的頭信息,默認爲空表示不過慮任何頭

測試 

服務端創建倆個方法請求路徑分別爲帶前綴,跟不帶前綴

 

 

 

請求http://localhost:50201/api/test1/hello

訪問結果

 

請求被轉發到        http://ip:port/test1/hello        因爲 strip-prefix爲false,所以請求有攜帶  test1

 

把strip-prefix 改爲true,再測試

 

過濾器:

Zuul的核心就是過慮器,通過過慮器實現請求過慮,身份校驗等

自定義過慮器需要繼承 ZuulFilter,ZuulFilter是一個抽象類,需要覆蓋它的四個方法,

1、 shouldFilter:返回一個Boolean值,判斷該過濾器是否需要執行。返回true表示要執行此過慮器,否則不執行。

2、 run:過濾器的業務邏輯。

3、 filterType:返回字符串代表過濾器的類型,如下

pre:請求在被路由之執行

routing:在路由請求時調用

post:在routing和errror過濾器之後調用

error:處理請求時發生錯誤調用

4、 filterOrder:此方法返回整型數值,通過此數值來定義過濾器的執行順序,數字越小優先級越高。

 


import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class LoginFilterTest extends ZuulFilter {

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 2;   //返回值越小,優先級越高
    }

    @Override
    public boolean shouldFilter() {
        return true;        //是否執行該過濾器
    }

    @Override
    public Object run() throws ZuulException {

        //zuul 提供的   requestcontext類,可以用此類獲取request,response
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        HttpServletResponse response = currentContext.getResponse();

        //取出頭部信息Authorization
        String authorization = request.getHeader("Authorization");

        if (StringUtils.isBlank(authorization)){
            //沒有攜帶信息
//            拒絕訪問
            currentContext.setSendZuulResponse(false);
            currentContext.setResponseStatusCode(200);  //設置響應碼

            //設置響應信息
            currentContext.setResponseBody("不是登陸請求啊");
            response.setContentType("text/plain;charset=UTF-8");
        }

        return null;
    }
}

 

 

測試

然後我使用 postman 發送請求 

 

一切順利,嘿嘿

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