摘要:其中內容如下網關的邏輯是讀取請求中的值,根據字段去內存的路由表中匹配路由,然后轉發請求到對應的微服務中去。排查測試接口本身的性能發現接口的可以達到。解決改寫代碼以實現同樣的功能之后進行測試,發現從提升到了,問題解決。
1. 問題
spring-cloud-gateway 作為統一的請求入口,負責轉發請求到相應的微服務中去。
采用的 Spring Cloud 的版本為 Finchley SR2。
測試一個接口的性能,發現 tps 只有 1000 req/s 左右就上不去了。
[root@hystrix-dashboard wrk]# wrk -t 10 -c 200 -d 30s --latency -s post-test.lua "http://10.201.0.28:8888/api/v1/json" Running 30s test @ http://10.201.0.28:8888/api/v1/json 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 188.34ms 110.13ms 2.00s 78.43% Req/Sec 106.95 37.19 333.00 77.38% Latency Distribution 50% 165.43ms 75% 243.48ms 90% 319.47ms 99% 472.64ms 30717 requests in 30.04s, 7.00MB read Socket errors: connect 0, read 0, write 0, timeout 75 Requests/sec: 1022.62 Transfer/sec: 238.68KB
其中 post-test.lua 內容如下:
request = function() local headers = {} headers["Content-Type"] = "application/json" local body = [[{ "biz_code": "1109000001", "channel": "7", "param": { "custom_id": "ABCD", "type": "test", "animals": ["cat", "dog", "lion"], "retcode": "0" } }]] return wrk.format("POST", nil, headers, body) end
網關的邏輯是讀取請求中 body 的值,根據 biz_code 字段去內存的路由表中匹配路由,然后轉發請求到對應的微服務中去。
2. 排查測試接口本身的性能:
[root@hystrix-dashboard wrk]# wrk -t 10 -c 200 -d 30s --latency -s post-test.lua "http://10.201.0.32:8776/eeams-service/api/v1/json" Running 30s test @ http://10.201.0.32:8776/eeams-service/api/v1/json 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 26.72ms 8.59ms 260.23ms 89.66% Req/Sec 752.18 101.46 0.94k 78.67% Latency Distribution 50% 23.52ms 75% 28.02ms 90% 35.58ms 99% 58.25ms 224693 requests in 30.02s, 50.83MB read Requests/sec: 7483.88 Transfer/sec: 1.69MB
發現接口的 tps 可以達到 7000+。
通過 spring-boot-admin 查看網關的 cpu、內存等占用情況,發現都沒有用滿;查看線程狀況,發現 reactor-http-nio 線程組存在阻塞情況。對于響應式編程來說,reactor-http-nio 線程出現阻塞結果是災難性的。
通過 jstack 命令分析線程狀態,定位阻塞的代碼(第 19 行):
"reactor-http-nio-4" #19 daemon prio=5 os_prio=0 tid=0x00007fb784d7f240 nid=0x80b waiting for monitor entry [0x00007fb71befc000] java.lang.Thread.State: BLOCKED (on object monitor) at java.lang.ClassLoader.loadClass(ClassLoader.java:404) - waiting to lock <0x000000008b0cec30> (a java.lang.Object) at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:93) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at org.springframework.util.ClassUtils.forName(ClassUtils.java:282) at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.registerWellKnownModulesIfAvailable(Jackson2ObjectMapperBuilder.java:753) at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.configure(Jackson2ObjectMapperBuilder.java:624) at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.build(Jackson2ObjectMapperBuilder.java:608) at org.springframework.http.codec.json.Jackson2JsonEncoder.(Jackson2JsonEncoder.java:54) at org.springframework.http.codec.support.AbstractCodecConfigurer$AbstractDefaultCodecs.getJackson2JsonEncoder(AbstractCodecConfigurer.java:177) at org.springframework.http.codec.support.DefaultServerCodecConfigurer$ServerDefaultCodecsImpl.getSseEncoder(DefaultServerCodecConfigurer.java:99) at org.springframework.http.codec.support.DefaultServerCodecConfigurer$ServerDefaultCodecsImpl.getObjectWriters(DefaultServerCodecConfigurer.java:90) at org.springframework.http.codec.support.AbstractCodecConfigurer.getWriters(AbstractCodecConfigurer.java:121) at org.springframework.http.codec.support.DefaultServerCodecConfigurer.getWriters(DefaultServerCodecConfigurer.java:39) at org.springframework.web.reactive.function.server.DefaultHandlerStrategiesBuilder.build(DefaultHandlerStrategiesBuilder.java:103) at org.springframework.web.reactive.function.server.HandlerStrategies.withDefaults(HandlerStrategies.java:90) at org.springframework.cloud.gateway.support.DefaultServerRequest. (DefaultServerRequest.java:81) at com.glsc.imf.dbg.route.RouteForJsonFilter.filter(RouteForJsonFilter.java:34) at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.lambda$filter$0(FilteringWebHandler.java:115) at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain$$Lambda$800/1871561393.get(Unknown Source) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:44)
最終定位到問題代碼為:
DefaultServerRequest req = new DefaultServerRequest(exchange); // 這行代碼存在性能問題 return req.bodyToMono(JSONObject.class).flatMap(body -> { ... });
這里的邏輯是我需要讀取請求中 body 的值,并轉化為 json,之后根據其中的特定字段去匹配路由,然后進行轉發。這里選擇了先把 exchange 轉化為 DefaultServerRequest,目的是為了使用該類的 bodyToMono 方法,可以方便的進行轉換。
3. 解決改寫代碼以實現同樣的功能:
return exchange.getRequest().getBody().collectList() .map(dataBuffers -> { ByteBuf byteBuf = Unpooled.buffer(); dataBuffers.forEach(buffer -> { try { byteBuf.writeBytes(IOUtils.toByteArray(buffer.asInputStream())); } catch (IOException e) { e.printStackTrace(); } }); return JSON.parseObject(new String(byteBuf.array())); }) .flatMap(body -> { ... });
之后進行測試,
[root@hystrix-dashboard wrk]# wrk -t 10 -c 200 -d 30s --latency -s post-test.lua "http://10.201.0.28:8888/api/v1/json" Running 30s test @ http://10.201.0.28:8888/api/v1/json 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 48.47ms 45.85ms 325.87ms 88.55% Req/Sec 548.13 202.55 760.00 80.01% Latency Distribution 50% 31.18ms 75% 39.44ms 90% 112.18ms 99% 227.19ms 157593 requests in 30.02s, 35.94MB read Requests/sec: 5249.27 Transfer/sec: 1.20MB
發現 tps 從 1000 提升到了 5000+,問題解決。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73052.html
摘要:由于不是線程安全的,故在方法上增加了同步操作,造成競爭等待。至此,整個多線程調優結束,通過充分優化同步競爭的方式,最終使得分線程記錄日志的性能比最原始的多線程寫同一文件提高了倍去鎖提高到倍,替換提高倍 背景 ??在一次項目的性能調優中,發現出現競爭瓶頸,導致在資源未使用滿的情況下,TPS已經無法提升。祭起JMC(JAVA MISSON CONTROL)飛行記錄器大法后,發現線程集中等待...
摘要:使用了多路復用技術的,就成了并發事件驅動的服務器。進程主要負責收集分發請求。同時進程也負責監控的狀態,保證高可靠性進程一般設置為跟核心數一致。所以才使得支持更高的并發。配置調優調整指要生成的數量最佳實踐是每個運行個工作進程。 Nginx 是如何實現高并發的? Nginx 采用的是多進程(單線程) & 多路IO復用模型。使用了 I/O 多路復用技術的 Nginx,就成了并發事件驅動的服務...
摘要:單線程集合本部分將重點介紹非線程安全集合。非線程安全集合框架的最新成員是自起推出的。這是標準的單線程陣營中唯一的有序集合。該功能能有效防止運行時造型。檢查個集合之間不存在共同的元素。基于自然排序或找出集合中的最大或最小元素。 【編者按】本文作者為擁有十年金融軟件開發經驗的 Mikhail Vorontsov,文章主要概覽了所有標準 Java 集合類型。文章系國內 ITOM 管理平臺 O...
閱讀 1341·2023-04-25 23:42
閱讀 2808·2021-11-19 09:40
閱讀 3520·2021-10-19 11:44
閱讀 3529·2021-10-14 09:42
閱讀 1860·2021-10-13 09:39
閱讀 3821·2021-09-22 15:43
閱讀 665·2019-08-30 15:54
閱讀 1448·2019-08-26 13:32