@Configuration
@RequiredArgsConstructor
public class GatewayConfig {
private final LoadBalancerClientFactory loadBalancerClientFactory;
private final LoadBalancerProperties properties;
/**
* 响应式框架中默认不会初始化HttpMessageConverters
*/
@Bean
@ConditionalOnMissingBean
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
}
/**
* 响应式框架中,无法使用feign处理
*/
@Bean
public LoadBalancerClient BlockingLoadBalancerClient() {
return new CustomBlockingLoadBalancerClient(loadBalancerClientFactory, properties);
}
}
package cn.need.cloud.gateway.config;
import lombok.SneakyThrows;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import reactor.core.publisher.Mono;
import java.util.concurrent.CompletableFuture;
/**
* 处理在响应式框架中使用openFeign导致block()/blockFirst()/blockLast() are blocking, which is not supported的问题
*/
public class CustomBlockingLoadBalancerClient extends BlockingLoadBalancerClient {
private final ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerClientFactory;
public CustomBlockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory, LoadBalancerProperties properties) {
//noinspection deprecation
super(loadBalancerClientFactory, properties);
this.loadBalancerClientFactory = loadBalancerClientFactory;
}
@SneakyThrows
@Override
public <T> ServiceInstance choose(String serviceId, Request<T> request) {
ReactiveLoadBalancer<ServiceInstance> loadBalancer = loadBalancerClientFactory.getInstance(serviceId);
if (loadBalancer == null) {
return null;
}
CompletableFuture<Response<ServiceInstance>> f = CompletableFuture.supplyAsync(() -> Mono.from(loadBalancer.choose(request)).block());
Response<ServiceInstance> loadBalancerResponse = f.get();
return loadBalancerResponse.getServer();
}
}