api網關是什么,SpringCloudZuul之API網關服務

 2023-11-23 阅读 25 评论 0

摘要:Spring Cloud 系列 eureka之服務治理完整過程搭建eureka之高可用的注冊中心eureka之詳解ribbon之客戶端負載均衡ribbon之配置詳解Hystrix之服務容錯保護Hystrix之使用詳解Hystrix之請求合并Hystrix之儀表盤以及Turbine集群監控Feign之聲明式服務調用Consul之服務發現和配置管
Spring Cloud 系列
  • eureka之服務治理完整過程搭建
  • eureka之高可用的注冊中心
  • eureka之詳解
  • ribbon之客戶端負載均衡
  • ribbon之配置詳解
  • Hystrix之服務容錯保護
  • Hystrix之使用詳解
  • Hystrix之請求合并
  • Hystrix之儀表盤以及Turbine集群監控
  • Feign之聲明式服務調用
  • Consul之服務發現和配置管理
  • Sleuth之分布式服務跟蹤
  • Zuul之API網關服務
  • Config之分布式配置中心
  • Config之服務端詳解
  • Config之客戶端詳解
  • Bus之消息總線
  • Stream之消息驅動的微服務
  • Stream之綁定器詳解
  • 重試機制

  • 系列源碼地址



文章目錄

      • 1. 入門
        • 1.1 導入依賴:
        • 1.2 添加啟動類
        • 1.3 添加配置文件
      • 2. 嵌入式 Zuul 反向代理
      • 3. 管理端點
      • 4. 扼殺模式和本地轉發

寫在前面

該文參考來自 程序猿DD 的Spring Cloud 微服務實戰一書,該文是作為閱讀了 spring cloud Zuul 一章的讀書筆記。書中版本比較老,我選擇了最新穩定版的 spring cloud Greenwich.SR2 版本,該版本較書中版本有些變動。非常感謝作者提供了這么好的學習思路,謝謝!文章也參考了 Spring-cloud-netflix 的官方文檔。


api網關是什么、路由是微服務體系結構的一個組成部分。例如 / 可能映射到你的 web應用程序,/api/users 映射到用戶服務,/api/shop 映射到商店服務。 Zuul 是一個來自 Netflix 的基于JVM 的路由器和服務端負載均衡器。DD 書里這樣一段話描述的非常好。“API 網關是一個更為智能的應用服務器,它的定義類似于面向對象設計模式中的 Facade 模式,它的存在就像是整個微服務架構系統的門面一樣,所有的外部客戶端訪問都需要經過它來進行調度和過濾。”

1. 入門

新建 api-gateway 工程

1.1 導入依賴:

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

1.2 添加啟動類

@EnableZuulProxy
@SpringCloudApplication
public class Application {public static void main(String[] args) {new SpringApplicationBuilder().sources(Application.class).web(WebApplicationType.SERVLET).run(args);}
}

@EnableZuulProxy 注解開啟 Zuul 的 API 網關服務功能。

1.3 添加配置文件

spring:application:name: api-gateway
server:port: 60010
eureka:client:service-url:defaultZone: http://localhost:1112/eureka/
zuul:routes:api-a:# 配置對路徑 /api-a/ 的所有訪問將會路由到 hello-service 服務上path: /api-a/**serviceId: hello-serviceapi-b:# 配置對路徑 /api-b/ 的所有訪問將會路由到 feign-consumer 服務上path: /api-b/**serviceId: feign-consumer

運行工程,訪問地址 /api-b/feign-consumer

以上是我們基于服務的路由方式,那么對于傳統的路由,我們應該怎樣配置呢?

zuul:routes:api-a-url:# 配置對路徑 /api-a-url/ 的所有訪問將會路由到  http://localhost:8080/provider/ 服務上path: /api-a-url/**url: http://localhost:8080/provider/api-b-url:# 配置對路徑 /api-b-url/ 的所有訪問將會路由到 http://localhost:8082/ 服務上path: /api-b-url/**serviceId: http://localhost:8082/

apicloud vue,該配置和上面基于服務的路由配置是一樣的,訪問地址/api-b-url/feign-consumer


2. 嵌入式 Zuul 反向代理

Spring Cloud創建了一個嵌入式 Zuul代理,以簡化UI應用程序希望對一個或多個后端服務進行代理調用的常見用例的開發。該特性對于用戶界面代理到所需的后端服務非常有用,從而避免了對所有后端獨立管理 CORS 和身份驗證問題的需要。

要啟用它,請使用@EnableZuulProxy注釋Spring引導主類。這樣做會導致本地調用被轉發到適當的服務。按照慣例,具有用戶ID的服務接收位于/users的代理的請求(去掉前綴)。代理使用Ribbon來定位要通過服務發現轉發到的服務實例。所有請求都在一個hystrix命令中執行,因此失敗將出現在hystrix指標中。一旦電路打開,代理服務器就不會試圖聯系服務。

Zuul Starter 并不包含服務發現客戶端,所以基于服務路由的方式,我們需要引入服務發現客戶端的依賴包。

簡單的路由方式并不會作為 HystrixCommand 執行,也不會用 Ribbon 來負載均衡多個 URL 。為了實現這一目標,我們可以使用靜態的服務器列表來指定 serviceId,如下:

zuul:routes:echo:path: /myusers/**serviceId: myusers-servicestripPrefix: truehystrix:command:myusers-service:execution:isolation:thread:timeoutInMilliseconds: ...myusers-service:ribbon:NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerListlistOfServers: https://example1.com,http://example2.comConnectTimeout: 1000ReadTimeout: 3000MaxTotalHttpConnections: 500MaxConnectionsPerHost: 100

3. 管理端點

udp服務器,默認情況下,使用 @EnableZuulProxy 注解后,將啟用兩個額外的端點(需要通過management.endpoints.web.exposure.include=routes,filters對外暴露):

  • routes

    使用 GET 請求訪問 /actuator/routes ,將返回路由映射列表:

    {"/api-a/**": "hello-service","/api-b/**": "feign-consumer","/api-a-url/**": "http://localhost:8080/provider/","/api-b-url/**": "http://localhost:8082/","/feign-consumer/**": "feign-consumer","/eureka-server-node1/**": "eureka-server-node1","/hello-service/**": "hello-service","/eureka-server-node2/**": "eureka-server-node2"
    }
    

    你會發現,這里包含了我們未在配置文件中配置的路徑映射。原因是引入服務發現客戶端后,會有服務的自動映射。我們可以通過 zuul.ignored-services='*' 來忽略它,對于我們額外的路由配置,并不會被忽略。

    為我們的配置文件添加完該配置后,再次訪問路由端點:

    {"/api-a/**":"hello-service","/api-b/**":"feign-consumer","/api-a-url/**":"http://localhost:8080/provider/","/api-b-url/**":"http://localhost:8082/"
    }
    

    SpringCloud?額外的,我們可以通過 ?format=details 或者 /routes/details 來獲取路由詳細信息:

    GET /routes/details.

    {"/api-a/**": {"id": "api-a","fullPath": "/api-a/**","location": "hello-service","path": "/**","prefix": "/api-a","retryable": false,"customSensitiveHeaders": false,"prefixStripped": true},"/api-b/**": {"id": "api-b","fullPath": "/api-b/**","location": "feign-consumer","path": "/**","prefix": "/api-b","retryable": false,"customSensitiveHeaders": false,"prefixStripped": true},"/api-a-url/**": {"id": "api-a-url","fullPath": "/api-a-url/**","location": "http://localhost:8080/provider/","path": "/**","prefix": "/api-a-url","retryable": false,"customSensitiveHeaders": false,"prefixStripped": true},"/api-b-url/**": {"id": "api-b-url","fullPath": "/api-b-url/**","location": "http://localhost:8082/","path": "/**","prefix": "/api-b-url","retryable": false,"customSensitiveHeaders": false,"prefixStripped": true}
    }
    

    通過 POST 請求訪問 /routes 端點將強制刷新已經存在的路由,我們可以通過 endpoints.routes.enabled = false 來禁用該端點。

  • filters

    GET 請求訪問 /filters 端點將返回過濾器類型映射。

    {"error": [{"class": "org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter","order": 0,"disabled": false,"static": true}],"post": [{"class": "org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter","order": 1000,"disabled": false,"static": true}],"pre": [{"class": "org.springframework.cloud.netflix.zuul.filters.pre.DebugFilter","order": 1,"disabled": false,"static": true}, {"class": "org.springframework.cloud.netflix.zuul.filters.pre.FormBodyWrapperFilter","order": -1,"disabled": false,"static": true}, {"class": "com.duofei.filter.AccessFilter","order": 0,"disabled": false,"static": true}, {"class": "org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter","order": -2,"disabled": false,"static": true}, {"class": "org.springframework.cloud.netflix.zuul.filters.pre.ServletDetectionFilter","order": -3,"disabled": false,"static": true}, {"class": "org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter","order": 5,"disabled": false,"static": true}],"route": [{"class": "org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter","order": 100,"disabled": false,"static": true}, {"class": "org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter","order": 10,"disabled": false,"static": true}, {"class": "org.springframework.cloud.netflix.zuul.filters.route.SendForwardFilter","order": 500,"disabled": false,"static": true}]
    }
    

    api網關聚合。其中,com.duofei.filter.AccessFilter 是我自定義的過濾器,代碼如下:

    public class AccessFilter extends ZuulFilter {private static Logger log = LoggerFactory.getLogger(AccessFilter.class);@Overridepublic String filterType() {return "pre";}@Overridepublic int filterOrder() {return 0;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() throws ZuulException {RequestContext currentContext = RequestContext.getCurrentContext();HttpServletRequest request = currentContext.getRequest();log.info("send {} request to {}",request.getMethod(),request.getRequestURL().toString());String accessToken = request.getParameter("accessToken");if (accessToken == null) {log.warn("access token is empty");currentContext.setSendZuulResponse(false);currentContext.setResponseStatusCode(401);return null;}log.info("access token ok");return null;}
    }
    

    還需要在啟動類中將該類添加到 Spring環境中:

        @Beanpublic AccessFilter accessFilter(){return new AccessFilter();}
    

4. 扼殺模式和本地轉發

遷移現有應用程序或 API 時的一種常見模式是“扼殺”舊端點,用不同的實現緩慢地替換它們。Zuul 代理在這方面是一個有用的工具,因為您可以使用它來處理來自舊端點的所有流量,但將一些請求重定向到新端點。

application.yml

 zuul:routes:first:path: /first/**url: https://first.example.comsecond:path: /second/**url: forward:/secondthird:path: /third/**url: forward:/3rdlegacy:path: /**url: https://legacy.example.com

在這個示例中,我們扼殺了 legacy 遺留程序;/first/** 中的路徑將映射到外部 URL 的新服務中,/second/** 的路徑將被轉發,因此我們可以在本地處理它,(像普通的 @RequestMapping), /third/** 中的路徑也被轉發,但前綴不同(例如/third/foo 將被轉發到/3rd/foo)。

網關、以上來自于 Spring 官方文檔,我對文檔中提到的功能做了實踐,在此做下記錄。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/187249.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息