网关性能测试
测试接口: /dw-service/jres/test
,该接口没有业务逻辑,直接返回字符串 jres-test。
涉及服务器: ip | 配置 | 运行服务 —|— |— 10.201.0.28 | 6 核,8G 内存 | gateway -Xmx2048m 10.201.0.29 | 6 核,8G 内存 | ms-auth -Xmx4096m 10.201.0.32 | 6 核,8G 内存 | dw-service -Xmx1024m
测试工具: 10.201.0.41 服务器安装 JMeter。
关闭 OAuth 认证
涉及服务:gateway;dw-service;外部请求访问网关,网关直接转发给 dw-service 微服务。 threads | avg | 99%Line | error | throughtput/sec | receive | send(KB/s) — |— |— |— |— |— |— 10 |3 |7 |0 |3020 |539 |589 50 |10 |35 |0 |4865 |871 |950 100 |20 |151 |0 |4800 |859 |936 200 |41 |520 |0 |4743 |849 |926 500 |157 |2228 |6.3 |3175 |951 |580
当 threads=50 时,dw-service 内存占用超过 1G,达到瓶颈。
当 zuul.semaphore.max-semaphores=100, threads=200 时,报错:java.lang.RuntimeException: could not acquire a semaphore for execution at com.netflix.hystrix.AbstractCommand.handleSemaphoreRejectionViaFallback
。
修改 zuul.semaphore.max-semaphores=200 即可。
当 threads=500 时,报错:java.net.BindException: Address already in use: connect at java.net.DualStackPlainSocketImpl.connect0(Native Method)
。
这是 windows 的 bug,当 JMeter 并发线程数较高时,可能会发生该错误。可以通过更改注册表解决:增大可分配的 tcp 连接端口数,减少处于 TIME_WAIT 状态的连接生存时间。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
新增 DWORD:
MaxUserPort: 65534
TcpTimedWaitDelay: 30
开启 OAuth 认证
涉及服务:gateway;dw-service;ms-auth;外部请求访问网关,网关先通过 feign 调用 OAuth 服务,确认该用户有权限后转发给 dw-service 服务。 threads | avg | 99%Line | error | throughtput | receive | send(KB/s) — |— |— |— |— |— |— 10 |21 |147 |0 |453 |81 |88 50 |20 |72 |0.2 |2447 |439 |478 100 |53 |664 |1.1 |1879 |339 |367
Cannot get Jedis connection
ms-auth 将用户的 token 信息存在 redis 中,jedis 配置如下:
spring.redis.pool:
max-active: 8
max-wait: 8
min-idle: 0
max-idle: 8
当 threads=10 时,0.2% 的请求报 Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool
错误。
修改 jedis 配置后问题解决。
spring.redis.pool:
max-active: 100
max-wait: 100
min-idle: 1
max-idle: 12
java.net.ConnectException: 无法指定被请求的地址
当 threads=50 时,0.2% 的请求报错:java.net.ConnectException: 无法指定被请求的地址 (connect failed)
at java.net.PlainSocketImpl.socketConnect(Native Method)
。
网上搜索了一下,一般这个是因为本地端口被占用完了的缘故。
通过
[root@gateway imf]# cat /proc/sys/net/ipv4/ip_local_port_range
32768 60999
查看本地可用端口为 28232 个(排除系统占用等);
gateway 的主要功能是认证授权,通过之后转发路由。因此涉及到的 http 连接主要包括:10.201.0.29:9999 的 auth 服务,以及 10.201.0.32:8767 的 dw-service 服务。
[root@gateway imf]# netstat -an | grep 10.201.0.28: | wc -l
28570
[root@gateway imf]# netstat -an | grep 10.201.0.29: | wc -l
28184
[root@gateway imf]# netstat -an | grep 10.201.0.32: | wc -l
128
[root@gateway imf]# netstat -an | grep 10.201.0.29:9999
tcp6 0 0 10.201.0.28:54682 10.201.0.29:9999 TIME_WAIT
tcp6 0 0 10.201.0.28:59942 10.201.0.29:9999 TIME_WAIT
tcp6 0 0 10.201.0.28:33243 10.201.0.29:9999 TIME_WAIT
tcp6 0 0 10.201.0.28:54634 10.201.0.29:9999 TIME_WAIT
tcp6 0 0 10.201.0.28:47410 10.201.0.29:9999 TIME_WAIT
tcp6 0 0 10.201.0.28:54770 10.201.0.29:9999 TIME_WAIT
有大量的连接 10.201.0.29:9999 的本地端口,tcp 状态为 TIME_WAIT。
默认 feign 采用 HttpURLConnection,没有使用线程池;可以通过配置线程池优化调用效率,并解决本地端口不够分配的异常。
feign:
httpclient:
enabled: true
@Configuration
public class HttpClientPool {
@Bean
public HttpClient httpClient() {
RequestConfig.Builder builder = RequestConfig.custom();
// 超时时间配置
builder.setSocketTimeout(10 * 1000);
builder.setConnectTimeout(3 * 1000);
RequestConfig defaultRequestConfig = builder.build();
// 连接池配置
final PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.MILLISECONDS);
poolingHttpClientConnectionManager.setMaxTotal(1000);
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(500);
// httpclient 配置
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());
httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
httpClientBuilder.setDefaultRequestConfig(defaultRequestConfig);
HttpClient client = httpClientBuilder.build();
return client;
}
}
更改后重新测试,threads=100 时,gateway 6 核 CPU 使用率 579%,达到瓶颈。 threads | avg | 99%Line | error | throughtput | receive | send(KB/s) — |— |— |— |— |— |— 10 |7 |13 |0 |1270 |227 |248 50 |17 |40 |0 |2870 |514 |560 100 |32 |142 |0 |3024 |541 |591 200 |65 |520 |0 |3028 |544 |591 500 |162 |686 |0 |3072 |549 |600 1000 |327 |874 |0 |3047 |549 |595
测试服务链路跟踪 sleuth 对性能的影响
spring:
zipkin:
base-url: 'http://zipkin-server:9411'
sleuth:
sampler:
percentage: 1
sleuth | threads | avg | 99%Line | error | throughtput | receive | send(KB/s) |
---|---|---|---|---|---|---|---|
100%跟踪 | 100 | 32 | 133 | 0 | 3070 | 541 | 591 |
1%跟踪 | 100 | 24 | 90 | 0 | 4030 | 722 | 787 |