请求失败或服务未及时响应 有关详细信息_「干货」从零开始的微服务搭建之路...
隨著公司的業(yè)務(wù)發(fā)展,有幸經(jīng)歷了從單體應(yīng)用遷移到分布式應(yīng)用,又從分布式應(yīng)用開始準備搭建微服務(wù)應(yīng)用,以下是公司從零開始搭建微服務(wù)的過程,記錄并分享出來,希望對大家有所幫助,我們先使用Spring Cloud GateWay作為網(wǎng)關(guān),由于目前還沒有服務(wù)發(fā)現(xiàn)組件,例如eurka,所以需要通過配置文件的方式配置Ribbon作負載均衡。所以以下重點講解Spring Cloud GateWay和Ribbon的搭配使用。
網(wǎng)關(guān)的由來
微服務(wù)提出后,單體應(yīng)用被拆分成多個服務(wù),為了對外提供統(tǒng)一入口,解耦客戶端與內(nèi)部服務(wù)。
單體架構(gòu)到微服務(wù)架構(gòu)演變
網(wǎng)關(guān)的作用
網(wǎng)關(guān)能做統(tǒng)一的路由轉(zhuǎn)發(fā)、熔斷、限流、安全認證、日志監(jiān)控等。
網(wǎng)關(guān)的作用
網(wǎng)關(guān)zuul與Spring Cloud Gateway對比
zuul與Spring Cloud Gateway對比
Spring Cloud Gateway核心概念
網(wǎng)關(guān)核心概念
1.路由(route) 路由是網(wǎng)關(guān)最基礎(chǔ)的部分,路由信息由一個ID、一個目的URL、一組斷言工廠和一組Filter組成。如果斷言為真,則說明請求URL和配置的路由匹配。
2.斷言(predicates) Java8中的斷言函數(shù),Spring Cloud Gateway中的斷言函數(shù)輸入類型是Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的斷言函數(shù)允許開發(fā)者去定義匹配來自Http Request中的任何信息,比如請求頭和參數(shù)等。
3.過濾器(filter) 一個標準的Spring webFilter,Spring Cloud Gateway中的Filter分為兩種類型,分別是Gateway Filter和Global Filter。過濾器Filter可以對請求和相應(yīng)進行處理。
Spring Cloud Gateway工作原理
網(wǎng)關(guān)工作原理
Spring Cloud Gateway核心處理流程如上圖所示,Gateway的客戶端向Spring Cloud Gateway發(fā)送請求,請求首先被HttpWebHandlerAdapter進行提取組裝成網(wǎng)關(guān)上下文,然后網(wǎng)關(guān)的上下文會傳遞到DispatcherHandler。DispatcherHandler是所有請求的分發(fā)處理器,DispatcherHandler主要負責分發(fā)請求對應(yīng)的處理器。比如請求分發(fā)到對應(yīng)的RoutePredicateHandlerMapping(路由斷言處理映射器)。路由斷言處理映射器主要作用用于路由查找,以及找到路由后返回對應(yīng)的FilterWebHandler。FilterWebHandler主要負責組裝Filter鏈并調(diào)用Filter執(zhí)行一系列的Filter處理,然后再把請求轉(zhuǎn)到后端對應(yīng)的代理服務(wù)處理,處理完畢之后將Response返回到Gateway客戶端。
路由斷言Factories整理
- After 路由斷言 Factory:在該日期時間之后發(fā)生的請求都將被匹配。
- Before 路由斷言 Factory:在該日期時間之前發(fā)生的請求都將被匹配。
- Between 路由斷言 Factory:在datetime1和datetime2之間的請求將被匹配。
- Cookie 路由斷言 Factory:Cookie 路由斷言 Factory有兩個參數(shù),cookie名稱和正則表達式。請求包含以cookie名稱且正則表達式為真的將會被匹配。
- Header 路由斷言 Factory:Header 路由斷言 Factory有兩個參數(shù),header名稱和正則表達式。請求包含以header名稱且正則表達式為真的將會被匹配。
- Host 路由斷言 Factory:Host 路由斷言 Factory包括一個參數(shù):host name列表。使用Ant路徑匹配規(guī)則,.作為分隔符。
- Method 路由斷言 Factory:Method 路由斷言 Factory只包含一個參數(shù): 需要匹配的HTTP請求方式。
- Path 路由斷言 Factory:Path 路由斷言 Factory 有2個參數(shù): 一個Spring PathMatcher表達式列表和可選。
- Query 路由斷言 Factory:Query 路由斷言 Factory 有2個參數(shù): 必選項 param 和可選項 regexp。
- RemoteAddr 路由斷言 Factory:RemoteAddr 路由斷言 Factory的參數(shù)為 一個CIDR符號(IPv4或IPv6)字符串的列表,最小值為1,例如192.168.0.1/16(其中192.168.0.1是IP地址并且16是子網(wǎng)掩碼)。
GatewayFilter Factories整理
- AddRequestHeader GatewayFilter Factory:對于所有匹配的請求,這將向下游請求的頭中添加header。
- AddRequestParameter GatewayFilter Factory:對于所有匹配的請求,這將向下游請求添加查詢字符串。
- AddResponseHeader GatewayFilter Factory:對于所有匹配的請求,這會將頭添加到下游響應(yīng)的header中。
- Hystrix GatewayFilter Factory:Hystrix 是Netflix開源的斷路器組件。Hystrix GatewayFilter允許你向網(wǎng)關(guān)路由引入斷路器,保護你的服務(wù)不受級聯(lián)故障的影響。
- FallbackHeaders GatewayFilter Factory:FallbackHeaders允許在轉(zhuǎn)發(fā)到外部應(yīng)用程序中的FallbackUri的請求的header中添加Hystrix異常詳細信息。
- PrefixPath GatewayFilter Factory:這將給所有匹配請求的路徑加前綴。
- PreserveHostHeader GatewayFilter Factory:該filter沒有參數(shù)。設(shè)置了該Filter后,GatewayFilter將不使用由HTTP客戶端確定的host header ,而是發(fā)送原始host header 。
- RequestRateLimiter GatewayFilter Factory:RequestRateLimiter使用RateLimiter實現(xiàn)是否允許繼續(xù)執(zhí)行當前請求。如果不允許繼續(xù)執(zhí)行,則返回HTTP 429 - Too Many Requests (默認情況下)。
- Redis RateLimiter:令牌桶的填充速率。
- RedirectTo GatewayFilter Factory:該過濾器有一個 status 和一個 url參數(shù)。status是300類重定向HTTP代碼,如301。該URL應(yīng)為有效的URL,這將是 Location header的值。
- RemoveRequestHeader GatewayFilter Factory:有一個name參數(shù). 這是要刪除的header的名稱。
- RemoveResponseHeader GatewayFilter Factory:有一個name參數(shù). 這是要刪除的header的名稱。
- RewritePath GatewayFilter Factory:包含一個 regexp正則表達式參數(shù)和一個 replacement 參數(shù). 通過使用Java正則表達式靈活地重寫請求路徑。
- RewriteResponseHeader GatewayFilter Factory:包含 name, regexp和 replacement 參數(shù).。通過使用Java正則表達式靈活地重寫響應(yīng)頭的值。
- SetPath GatewayFilter Factory:它提供了一種通過允許路徑的模板化segments來操作請求路徑的簡單方法。使用Spring Framework中的URI模板,允許多個匹配segments。
- SetStatus GatewayFilter Factory:SetStatus GatewayFilter Factory 包括唯一的 status參數(shù).必須是一個可用的Spring HttpStatus。
- StripPrefix GatewayFilter Factory:parts參數(shù)指示在將請求發(fā)送到下游之前,要從請求中去除的路徑中的節(jié)數(shù)。
- Retry GatewayFilter Factory:Retry GatewayFilter Factory包括 retries, statuses, methods和 series 參數(shù)。
- RequestSize GatewayFilter Factory:當請求大小大于允許的限制時,RequestSize GatewayFilter Factory可以限制請求不到達下游服務(wù)。過濾器以RequestSize作為參數(shù),這是定義請求的允許大小限制(以字節(jié)為單位)。
Ribbon的LoadBalancer的主要組件
Ribboon主要組件
IPing:客戶端用于快速檢查服務(wù)器當時是否處于活動狀態(tài)(心跳檢測)IRule:負載均衡策略,用于確定從服務(wù)器列表返回哪個服務(wù)器ServerList:可以響應(yīng)客戶端的特定服務(wù)的服務(wù)器列表ServerListFilter:可以動態(tài)獲得的具有所需特征的候選服務(wù)器列表的過濾器ServerListUpdater:用于執(zhí)行動態(tài)服務(wù)器列表更新IRule
RoundRobinRule:系統(tǒng)默認的規(guī)則,通過簡單輪詢服務(wù)列表來選擇服務(wù)器。AvailabilityFilteringRule:該規(guī)則會忽略一下服務(wù)器。無法連接的服務(wù)器。默認情況下,3次連接失敗,服務(wù)器會被置為短路的狀態(tài),狀態(tài)持續(xù)為30秒;再次連接失敗,短路的狀態(tài)持續(xù)時間將會以幾何數(shù)增加。可以通過修改connectionFailureCountThreshold屬性,配置連接失敗的次數(shù)。并發(fā)數(shù)過高的服務(wù)器。可以修改ActiveConnectionsLimit屬性來設(shè)置最高并發(fā)數(shù)。WeightedResponseTimeRule: 為每個服務(wù)器賦予一個權(quán)重值,服務(wù)器的響應(yīng)時間越長,權(quán)重就越小,隨機選擇服務(wù)器,權(quán)重值有可能會決定服務(wù)器的選擇。ZoneAvoidanceRule: 該規(guī)則以區(qū)域、可用服務(wù)器為基礎(chǔ)進行服務(wù)器選擇。使用Zone對服務(wù)器進行分類。BestAvailableRule: 忽略短路的服務(wù)器,并選擇并發(fā)數(shù)較低的服務(wù)器。RandomeRule: 隨機選擇可用的服務(wù)器。RetryRule: 含有重試的選擇邏輯。IPing
檢查實例是否存活。如何ping。實現(xiàn)類:
NoOpPing: 不進行Ping。DummyPing:默認實現(xiàn),標記存活的服務(wù)器。NIWSDiscoveryPing: 假設(shè)服務(wù)器存活。PingUrl: 一種健康檢查的ping。ServerList
獲取服務(wù)器列表。
DiscoveryEnabledNIWSServerList: 從Eureka 客戶端獲取服務(wù)器列表。DomainExtractingServerList: 基于domain獲取服務(wù)列表。ConfigurationBasedServerList: 從配置中獲取服務(wù)器列表ServerListFilter
在獲取的服務(wù)器列表中進行獲取。
ZoneAffinityServerListFilter: 根據(jù)區(qū)域親緣關(guān)系過濾服務(wù)器。在使用這個過濾器時,需要開啟CommonClientConfig#EnableZoneAffinity或者CommonClientConfigKey#EnableZoneExclusivity=true。開啟后,同一個區(qū)域之外的服務(wù)器將被過濾。默認情況下,區(qū)域親和力和排他性是關(guān)閉的,并且
不會過濾任何內(nèi)容。ZonePreferenceServerListFilter: 主動首選本地區(qū)域的過濾器。ServerListSubSetFilter: 服務(wù)器列表過濾器,將負載均衡器使用的服務(wù)器數(shù)量限制為所有服務(wù)器的子集。
ServerListUpdater
更新服務(wù)器列表。
EurekaNotificationServerListUpdater: 利用Eureka的時間監(jiān)聽器觸發(fā)LB緩存更新。PollingServerListUpdater: 默認的策略動態(tài)更新服務(wù)器列表。IClientConfig
- IClientConfig的實現(xiàn)類為DefaultClientConfigImpl。DefaultClientConfigImpl是默認的客戶端配置,可以從Archaius ConfigurationManager加載屬性。
ILoadBalancer
LoadBalancer的組成:
LoadBalancer的實現(xiàn)類:
BaseLoadBalancer: 基本的實現(xiàn),ping確定存活的服務(wù)器列表。DynamicServerListLoadBalancer: 動態(tài)獲取的服務(wù)器列表。ZoneAwareLoadBalancer: LoadBalancer將計算并檢查所有可用區(qū)域的區(qū)域統(tǒng)計信息。如果任何區(qū)域的“平均活動請求數(shù)”已達到配置的閾值,則該區(qū)域?qū)幕顒臃?wù)器列表中刪除。如果多個區(qū)域已達到閾值,則將刪除每臺服務(wù)器上最活躍請求的區(qū)域。一旦刪除了最壞的區(qū)域,
將在其余區(qū)域中選擇一個區(qū)域,其概率與其實例數(shù)成正比。服務(wù)器將從具有指定規(guī)則的選定區(qū)域返回。每個區(qū)域相關(guān)的負載平衡決策都是在最新統(tǒng)計信息的幫助下實時做出的。
代碼實踐
pom.xml增加SpringCloud Gateway和Ribbon依賴
org.springframework.boot spring-boot-starter-parent 2.0.3.RELEASEorg.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-actuator org.springframework.cloud spring-cloud-starter-gateway org.springframework.cloud spring-cloud-starter-netflix-ribbon代碼方式配置網(wǎng)關(guān)
@SpringBootApplication@RestControllerpublic class DemoGatewayApplication { public static void main(String[] args) { SpringApplication.run(DemoGatewayApplication.class, args); } @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route(r -> r .path("/refund/**") .filters(f -> f.addRequestHeader("Hello", "World")) .uri("http://manage-test.payplatform.speiyou.cn/") ).build(); }}yml方式配置網(wǎng)關(guān)
spring: application: name: gateway-service cloud: gateway: routes: - id: merchant uri: lb://merchant-load-balanced-service predicates: - Path=/merchant/** - Method=POST - id: split uri: lb://split-load-balanced-service predicates: - Path=/split/** filters: - RewritePath=/split, /ledger-split #重寫url - id: cashier uri: lb://cashier-load-balanced-service predicates: - Path=/cashier/** filters: - StripPrefix=1 #將cashier過濾掉 #ribbon全局配置ribbon: ConnectTimeout: 1000 #服務(wù)請求連接超時時間(毫秒) ReadTimeout: 3000 #服務(wù)請求處理超時時間(毫秒) OkToRetryOnAllOperations: true #對超時請求啟用重試機制 MaxAutoRetriesNextServer: 1 #切換重試實例的最大個數(shù) MaxAutoRetries: 1 # 切換實例后重試最大次數(shù) NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #負載均衡算法 NFLoadBalancerPingClassName: com.talpay.gateway.config.HealthCheck #健康檢查 NFLoadBalancerPingInterval: 20 #設(shè)置健康檢查間隔,單位秒,默認30秒merchant-load-balanced-service: ribbon: listOfServers: 192.168.xxx.xxx:8080split-load-balanced-service: ribbon: listOfServers: 192.168.xxx.xxx:8081cashier-load-balanced-service: ribbon: listOfServers: 192.168.xxx.xxx:8080Ribbon服務(wù)健康檢查
@Slf4j@Componentpublic class HealthCheck implements IPing{ @Autowired private RestTemplate restTemplate; @Value("${dingtalk.url}") private String dingtalkURL; //釘釘報警url @Override public boolean isAlive(Server server) { String url = "http://"+ server.getId()+ "/actuator/health"; try { ResponseEntity heath = restTemplate.getForEntity(url, String.class); if (heath.getStatusCode() == HttpStatus.OK) { log.info("ping " + url + " success "); return true; } log.info("ping " + url + " error and response is " + heath.getBody()); return false; } catch (Exception e) { log.error("ping " + url + " failed"); DingRebotSendUtil.send(dingtalkURL,new TextMessage("網(wǎng)關(guān)|ping:" + url + " failed")); return false; } }}自定義GlobalFilter
@Componentpublic class LogGlobalFilter implements GlobalFilter { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest serverHttpRequest= exchange.getRequest(); String url = serverHttpRequest.getURI().toString(); System.out.println("url ------>: " + url);//打印每次請求的url return chain.filter(exchange); }}測試結(jié)果:
第一次觸發(fā)
第二次觸發(fā)
以上為真實測試數(shù)據(jù),第一次觸發(fā)鏈接到生產(chǎn)環(huán)境,第二次觸發(fā)鏈接到仿真環(huán)境。
不斷分享開發(fā)過程用到的技術(shù)和面試經(jīng)常被問到的問題,如果您也對IT技術(shù)比較感興趣可以「關(guān)注」我
總結(jié)
以上是生活随笔為你收集整理的请求失败或服务未及时响应 有关详细信息_「干货」从零开始的微服务搭建之路...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: factorybean 代理类不能按照类
- 下一篇: python版本切换_Ubuntu18.