记录一次线上网关bug---gateway
问题描述
最近一次压测的过程中发现一个奇怪的bug,调A服务的接口,但是ip和端口却是B服务的,调B服务的接口,但是ip和端口却是A服务的。
比如调用A服务的接口,本来应该是 http://192.168.10.10:8100/api/testA,调用B服务的接口,应该是 http://192.168.10.10:8200/api/testB,结果却变成了 http://192.168.10.10:8100/api/testB和 http://192.168.10.10:8200/api/testA。
而且这是偶发事件,只有在压测的时候才会出现
排查
我们首先怀疑的是服务的端口是不是谁配置错了,检查一遍很快排除掉了。因为这是偶发现象,所以如果是配置错了,那肯定是每次请求都报错,而事实上是偶尔报错。后来同事发现了调用微服务的WebClient是个单例,那么好,问题肯定是出在单例上面了。下面是我们原先的代码:
原先的代码
注册WebClient
@Bean
@LoadBalanced // 如果不添加,无法通过服务名进行调用,只能通过ip调用
public WebClient.Builder serviceA() {
return WebClient.builder();
}
微服务调用WebClient
public Mono<Result<ClaimsObjVO>> requestA(String accessToken) {
return authWebBuilder.baseUrl("http://demo-serviceA").build().get().uri(uriBuilder ->
uriBuilder.path("/api/testA").queryParam("accessToken", accessToken).build()
).retrieve().bodyToMono(new ParameterizedTypeReference<Result<ClaimsObjVO>>() {
});
Result<ClaimsObjVO> claimsObjVOResult = authFeignClient.verifyToken(accessToken);
return Mono.just(claimsObjVOResult);
}
第二个服务
public Mono<Result<String>> requestB(Long userId) {
return webBuilder.baseUrl("http://demo-serviceB").build().get().uri(uriBuilder ->
uriBuilder.path("/api/testB").queryParam("userId", userId).build()
).retrieve().bodyToMono(new ParameterizedTypeReference<Result<String>>() {
});
}
从上面的代码可以看出来,两个服务用的是同一个WebClient,高并发的情况下,当线程1完成了authWebBuilder.baseUrl("http://demo-serviceA").build()以后就已经把WebClient的请求地址给确定了,这时候线程2调用B服务的接口时就会使用A的WebClient去调用,导致异常的发生。
解决方案
解决方案有两种,一种是不要用WebClient去请求微服务,这个当时是因为我们升级了高版本的springcloud导致feign调用有问题,所以改成了WebClient。
第二种是给每个微服务地址创建一个webclient的实例,代码如下
改造后代码
@Bean("serviceA")
@LoadBalanced // 如果不添加,无法通过服务名进行调用,只能通过ip调用
public WebClient.Builder serviceA() {
return WebClient.builder();
}
@Bean("serviceB")
@LoadBalanced // 如果不添加,无法通过服务名进行调用,只能通过ip调用
public WebClient.Builder serviceB() {
return WebClient.builder();
}
调用的时候指定注入不同的对象即可
private final WebClient.Builder webBuilder;
public UserWebClient(@Qualifier("serviceA") WebClient.Builder webBuilder) {
this.webBuilder = webBuilder;
}

浙公网安备 33010602011771号