Api Gateway Zuul簡介及SpringCloud中的使用

Zuul 的官方介紹是
“Zuul is the front door for all requests from devices and web sites to the backend of the Netflix streaming application. As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security. It also has the ability to route requests to multiple Amazon Auto Scaling Groups as appropriate.”
大致是說zuul是設備和網站到Netflix後臺應用程序的所有的請求的前門,是一個邊緣化應用程序,它的創建是爲了實現動態路由,監控,彈性,和安全性, 它還能夠根據需要將請求路由到多個Amazon Auto Scaling組。

其實zuul主要實現的功能就是API Gateway(api網關)的功能,爲什麼使用api gateway:
  • 客戶端會多次請求不同的微服務,導致客戶端複雜度增加,使用網關時客戶端只與網關交互,降低客戶端的調用邏輯的複雜度,同時網關也可以實現認證邏輯簡化內部服務的之間相互調用的複雜度。
  • 對不同客戶端的支持及數據的聚合,如一個網站有web端,手機端,頁面所需的數據有同有異,可以將數據整合或者裁剪,減少客戶端的請求次數,比如BFF架構。
  • 可以更好的對項目的微服務封裝,可將項目的微服務統一封裝在一個內網環境中,只通過網關提供服務,同時網關也可以對安全,認證,監控,防禦單獨強化。
在springcloud使用zuul:
    1:除了添加eureka依賴外,添加zuul依賴包:
        
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

     2:在啓動類上使用@EnableZuulProxy 啓用zuul
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class, args);
    }
}
    3:配置文件application.yml
    
spring:
    application:
        name: micoserice-gateway-zuul
server:
    port: 8090
eureka:
    client:
        serviceUrl:
            defaultZone: http://localhost:8761/eureka/
    instance:
        prefer-ip-address: true
        instance-id: ${spring.application.name}:${server.port}

啓動運行:

如圖我這裏啓動了三個服務,zuul註冊到Eureka-service爲服務後默認情況下是構建PAI-GATEWAY,訪問時只要zuul-host/appname/api
如我這裏訪問:http://localhost:8090/micoserice-user/user/getuser,當調用服務有多個時,zuul是實現了負載均衡的。

zuul中使用hystrix的回退:
代碼如下
/**
* @author wxy
* zuul中使用hystrix的回退
*/
@Component
public class MyFallbackProvider implements ZuulFallbackProvider {
    @Override
    public String getRoute() {
        //路由配置micoserice-user,如果全部用"*"代替
        return "micoserice-user";
    }

    @Override
    public ClientHttpResponse fallbackResponse() {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                //回退的狀態碼
                return HttpStatus.OK;
             }

            @Override
            public int getRawStatusCode() throws IOException {
                //數字類型狀態碼
                return 200;
               }

            @Override
            public String getStatusText() throws IOException {
                //狀態文本
                return "ok";
            }

            @Override
            public void close() { }

            @Override
            public InputStream getBody() throws IOException {
                //回退響應體
                return new ByteArrayInputStream("服務不可用稍後再試".getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                //header設置
                HttpHeaders headers = new HttpHeaders();
                MediaType mediaType = new MediaType("application","json", Charset.forName("UTF-8"));
                headers.setContentType(mediaType);
                return headers;
            }
        };
    }
}
添加回退後當訪問micoserice-user 微服務失敗後將會返回“服務不可用稍後再試”。
zuul過濾器:
/**
* @author wxy
* zuul過濾器
* zuul中定義了四種標準過濾類型,這些過濾類型對應請求的生命週期
*
* PRE:這種過濾類型在請求被路由之前調用。可利用這種過濾器實現身份驗證,在集羣中選擇請求的微服務,記錄調試信息等。
*
* ROUTING:這種過濾器將請求路由到微服務。這種過濾用於構建發送給微服務的請求,
* 並可以使用Apache HttpClient,Fegin,Ribbon請求微服務。
*
* POST:這種過濾器在路由到微服務以後執行。這種過濾器可用來微響應添加標準的http header,
* 蒐集統計信息和指標,將響應發送給客戶端。
*
* ERROR:在其他階段發生錯誤時執行該過濾器。
*
*/
public class RequestLogFilter extends ZuulFilter {
    private static Logger logger = LoggerFactory.getLogger(RequestLogFilter.class);
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
   public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext requestContext =RequestContext.getCurrentContext();
         HttpServletRequest request = requestContext.getRequest();
        logger.info(String.format("send %s request to %s",request.getMethod(),request.getRequestURL().toString()));
        return null;
    }
}
//在啓動類下添加Bean
@Bean
public RequestLogFilter getRequestLogFilter(){
return new RequestLogFilter();
}
本文參考




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