1. 程式人生 > >springcloud實踐(二)之api網關:zuul

springcloud實踐(二)之api網關:zuul

actor 控制 patch isp where url 大文件上傳 html base

zuul是什麽?

  • front door. API Gateway.Zuul is a JVM based router and server side load balancer by Netflix.
  • 所有請求的入口。
  • As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security. 作為邊界應用服務,zuul能實現動態路由、監控、彈性與安全性。
  • 用groovy編寫。

Netflix uses Zuul for the following:

Authentication 認證
Insights 洞察力
Stress Testing 壓力測試
Canary Testing 金絲雀測試
Dynamic Routing 動態路由
Service Migration 服務遷移
Load Shedding 減載
Security 安全
Static Response handling 靜態響應處理
Active/Active traffic management

如果以後想設計網關,可按照上面進行対飈設計。

使用註意事項

  1. If you need your routes to have their order preserved you need to use a YAML file
    as the ordering will be lost using a properties file.如果你希望按照書寫順序來執行路由規則,則必須使用YAML文件,不能使用properties

Embedded Zuul Reverse Proxy

使用代理,方便前端調用後端服務,避免CORS(跨域資源訪問)和權限問題,

  • @EnableZuulProxy
  • The proxy uses Ribbon to locate an instance to forward to via discovery, and all requests are executed in a hystrix command, so failures will show up in Hystrix metrics, and once the circuit is open the proxy will not try to contact the service.代理通過服務發現調用服務,通過ribbon定位實例,所有請求通過hystrix命令模式來執行。失敗信息都會在收集在hystrix指標體系中,一旦進入熔斷模式,代理將無法訪問服務。
  • 至少需要集成discovery client,如eureka

Zuul Http Client

The default HTTP client used by zuul is now backed by the Apache HTTP Client instead of the deprecated Ribbon RestClient.

To use RestClient or to use the okhttp3.OkHttpClient set
ribbon.restclient.enabled=true 
or 
ribbon.okhttp.enabled=true 

現在默認使用apache client.

Cookies and Sensitive Headers

對cookie和headers敏感,就是說可以制定headers的規則來過濾請求。Spring Cloud Netflix 1.1 以上版本才有此功能。

 zuul:
  routes:
    users:
      path: /myusers/**
      sensitiveHeaders: Cookie,Set-Cookie,Authorization  # blacklist,如果不過濾,則須顯式設為空。
      url: https://downstream
      
set globally by setting zuul.sensitiveHeaders      
      

Strangulation Patterns and Local Forwards

應用如何由老版本向新版本?

  • 扼殺模式(使其慢慢窒息的方式):一部分調用老應用,一部分調用新應用。
  • hystrix也可以提供控制新老應用的切換

Uploading Files through Zuul

小文件可以通過zuul proxy,大文件通過 Spring DispatcherServlet。

Query String Encoding

The result can be different than the original input if it was encoded using Javascript’s encodeURIComponent() method for example. While this causes no issues in most cases, some web servers can be picky with the encoding of complex query string.

zuul:
  forceOriginalQueryStringEncoding: true

Note: This special flag only works with SimpleHostRoutingFilter and you loose the ability to easily override query parameters with RequestContext.getCurrentContext().setRequestQueryParams(someOverriddenParameters) since the query string is now fetched directly on the original HttpServletRequest.

Disable Zuul Filters

默認會使用很多filters,可采用如下方式禁止

set zuul.

zuul.SendResponseFilter.post.disable=true

Zuul Timeouts

  • ==zuul在使用服務發現和路由時,需配置超時參數如下:==
  • If Zuul is using service discovery than you need to configure these timeouts via Ribbon properties, ribbon.ReadTimeout and ribbon.SocketTimeout.

  • If you have configured Zuul routes by specifying URLs than you will need to use zuul.host.connect-timeout-millis and zuul.host.socket-timeout-millis.

Rewriting Location header

If Zuul is fronting a web application then there may be a need to re-write the Location header when the web application redirects through a http status code of 3XX。==當通過3XX重定向時,需要重寫header,否則會重定向到web url而不是zuul url.==

重寫 filter

import org.springframework.cloud.netflix.zuul.filters.post.LocationRewriteFilter;
...

@Configuration
@EnableZuulProxy
public class ZuulConfig {
    @Bean
    public LocationRewriteFilter locationRewriteFilter() {
        return new LocationRewriteFilter();
    }
}

==Note==:不一定適應所有情況,萬一就是要重定向到外部url.

Zuul Developer Guide

The Zuul Servlet

Zuul is implemented as a ==Servlet==. For the general cases, Zuul is ==embedded into the Spring Dispatch mechanism==. This allows Spring MVC to be in control of the routing.
zuul是servlet.zuul嵌入springd的請求轉發機制,這樣spring mvc由它來控制路由。

zuul一般配置緩存請求,當大文件上傳時例外。

by default:/zuul. zuul.servlet-path

Zuul RequestContext

RequestContext

  • 請求數據保存在ThreadLocal中,Information about where to route requests, errors and the actual HttpServletRequest and HttpServletResponse are stored there.
  • RequestContext繼承了ConcurrentHashMap

@EnableZuulProxy vs. @EnableZuulServer

@EnableZuulProxy > @EnableZuulServer, 多了路由功能。The additional filters in the "proxy" enable routing functionality.

Filters

技術分享圖片

How to Write a Route Filter

extends ZuulFilter 繼承以下三類過濾器:

  • Pre Filter
  • Route Filter
  • Post Fitler
  • 在run()中,對request、OkHttpClient、response做修改。

How Zuul Errors Work

The SendErrorFilter is only run if RequestContext.getThrowable() is not null.

It then sets specific javax.servlet.error.* attributes in the request and forwards the request to the Spring Boot error page. 如何設置該屬性?
ajax請求如何處理?

Zuul Eager Application Context Loading

Ribbon clients are by default lazily loaded up by Spring Cloud on first call.Ribbon clients默認為延遲加載

修改配置,讓其在應用啟動時加載:

zuul:
  ribbon:
    eager-load:
      enabled: true

practice

通過url映射的方式來實現zull的轉發有局限性

stripPrefix默認為true。This means that all calls such as "/myusers/101" will be forwarded to "/101" on the "users" service.

spring.application.name=gateway-service-zuul
server.port=8888
#這裏的配置表示,訪問/it/** 直接重定向到http://www.ityouknow.com/**
zuul.routes.baidu.path=/it/**
zuul.routes.baidu.url=http://www.ityouknow.com/

通過serviceId(即application name)來轉發

zuul:
  routes:
    producer:
      path: /wifi/**
      serviceId: wifi-service
  strip-prefix: true

zuul高可用

參數優化

  1. 為Spring Cloud Ribbon配置請求重試
zuul.host.connect-timeout-millis 
zuul.host.socket-timeout-millis
zuul.eureka.[service id].semaphore.maxSemaphores: 128

spring.cloud.loadbalancer.retry.enabled=true

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000

hello-service.ribbon.ConnectTimeout=250
hello-service.ribbon.ReadTimeout=1000

zuul存在的問題

在實際使用中我們會發現直接使用Zuul會存在諸多問題,包括:

  • 性能問題:當存在大量請求超時後會造成Zuul阻塞,目前只能通過橫向擴展Zuul實例實現對高並發的支持;

  • WebSocket的支持問題: Zuul中並不直接提供對WebSocket的支持,需要添加額外的過濾器實現對WebSocket的支持;
    技術分享圖片

  • 缺少請求速率限制功能,已有第三方jar包提供:zuul進行rate limit
  • 性能問題解決方案:集群、高可用

    Zuul is just a stateless service with an HTTP endpoint, hence, we can have as many Zuul instances as we need.
  • zuul多個節點啟動,自身也可以作為服務,註冊到eureka上。
    技術分享圖片

High availability when client is not a Eureka Client. The Zuul instances, in this case, will be running behind a load balancer such as HAProxy, or a hardware load balancer like NetScaler:

技術分享圖片

高可用負載均衡選型haproxy vs nginx

選擇haproxy,理由如下:

  • 從定位上選擇,haproxy組件功能單一,只做LB; nginx重點是web服務器,替換的是apache,同時具備lb的作用
  • haproxy有心跳檢測,nginx需要集成第三方插件
  • haproxy有監控頁面
  • haproxy負載均衡算法更多、更好。
  • 支持虛擬主機

如果擔心LB單點問題,可采用keepalived+haproxy.

網站並發達到一定程度之後,為了提高穩定性和轉發效率,可以使用LVS、畢竟LVS比Nginx/HAproxy要更穩定,轉發效率也更高。不過維護LVS對維護人員的要求也會更高,投入成本也更大。

展望

zuul已經開源幾年了,現在已有新的開源項目Spring Cloud Gateway,剛開源不久,還不成熟。從其公布的特性,集成了服務發現、斷路器、限流等功能。

Spring Cloud Gateway features:

  • Built on Spring Framework 5, Project Reactor and Spring Boot 2.0
  • Able to match routes on any request attribute.
  • Predicates and filters are specific to routes.
  • Hystrix Circuit Breaker integration.
  • Spring Cloud DiscoveryClient integration
  • Easy to write Predicates and Filters
  • Request Rate Limiting
  • Path Rewriting

參考文獻

  1. zull wiki
  2. spring-cloud-netflix官網手冊
  3. springcloud(十):服務網關zuul初級篇 ----環境搭建入門參考
  4. Zuul的高可用
  5. API GateWay(網關)那些兒事
  6. zuul 參數調優
  7. zuul進行rate limit

tips:本文屬於自己學習和實踐過程的記錄,很多圖和文字都粘貼自網上文章,沒有註明引用請包涵!如有任何問題請留言或郵件通知,我會及時回復。

springcloud實踐(二)之api網關:zuul