Spring Cloud 线上微服务实例都是2个起步,如果出问题后,在没有ELK等日志分析平台,如何确定调用到了目标服务的那个实例,以此来排查问题
成都创新互联公司专业为企业提供神池网站建设、神池做网站、神池网站设计、神池网站制作等企业网站建设、网页设计与制作、神池企业网站模板建站服务,十载神池做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。
图片
可以看到服务有几个实例是上线,并且最终调用了那个实例
图片
考虑到Spring Cloud在版本升级中使用了两种负载均衡实现,Robin和LoadBalancer,下面我们提供两种实现方案
/**
* 因为调用目标机器的时候,如果目标机器本身假死或者调用目标不通无法数据返回,那么feign无法打印目标机器。这种场景下我们需要在调用失败(目标机器没有返回)的时候也能把目标机器的ip打印出来,这种场景需要我们切入feign选择机器的逻辑,注入我们自己的调度策略(默认是roundrobin),在里面打印选择的机器即可。
*/
@Slf4j
public class FeignRule extends RoundRobinRule {
@Override
public Server choose(Object key) {
Server server = super.choose(key);
if (Objects.isNull(server)) {
log.info("server is null");
return null;
}
log.info("feign rule ---> serverName:{}, choose key:{}, final server ip:{}", server.getMetaInfo().getAppName(), key, server.getHostPort());
return server;
}
@Override
public Server choose(ILoadBalancer lb, Object key) {
Server chooseServer = super.choose(lb, key);
List reachableServers = lb.getReachableServers();
List allServers = lb.getAllServers();
int upCount = reachableServers.size();
int serverCount = allServers.size();
log.info("serverName:{} upCount:{}, serverCount:{}", Objects.nonNull(chooseServer) ? chooseServer.getMetaInfo().getAppName() : "", upCount, serverCount);
for (Server server : allServers) {
if (server instanceof DiscoveryEnabledServer) {
DiscoveryEnabledServer dServer = (DiscoveryEnabledServer) server;
InstanceInfo instanceInfo = dServer.getInstanceInfo();
if (instanceInfo != null) {
InstanceInfo.InstanceStatus status = instanceInfo.getStatus();
if (status != null) {
log.info("serverName:{} server:{}, status:{}", server.getMetaInfo().getAppName(), server.getHostPort(), status);
}
}
}
}
return chooseServer;
}
}
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Configuration;
/**
* @description:feign 配置
*/
@Configuration
@RibbonClients(defaultConfiguration = {FeignRule.class})
public class FeignConfig {
}
@Slf4j
public class CustomRoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
final AtomicInteger position;
final String serviceId;
ObjectProvider serviceInstanceListSupplierProvider;
public CustomRoundRobinLoadBalancer(ObjectProvider serviceInstanceListSupplierProvider, String serviceId) {
this(serviceInstanceListSupplierProvider, serviceId, (new Random()).nextInt(1000));
}
public CustomRoundRobinLoadBalancer(ObjectProvider serviceInstanceListSupplierProvider, String serviceId, int seedPosition) {
this.serviceId = serviceId;
this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
this.position = new AtomicInteger(seedPosition);
}
public Mono> choose(Request request) {
ServiceInstanceListSupplier supplier = this.serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
return supplier.get(request).next().map((serviceInstances) -> {
return this.processInstanceResponse(supplier, serviceInstances);
});
}
private Response processInstanceResponse(ServiceInstanceListSupplier supplier, List serviceInstances) {
Response serviceInstanceResponse = this.getInstanceResponse(serviceInstances);
if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
((SelectedInstanceCallback)supplier).selectedServiceInstance((ServiceInstance)serviceInstanceResponse.getServer());
}
return serviceInstanceResponse;
}
private Response getInstanceResponse(List instances) {
if (instances.isEmpty()) {
if (log.isWarnEnabled()) {
log.warn("No servers available for service: " + this.serviceId);
}
return new EmptyResponse();
} else {
int pos = this.position.incrementAndGet() & Integer.MAX_VALUE;
ServiceInstance instance = instances.get(pos % instances.size());
log.info("serverName:{} upCount:{}",instance.getServiceId(),instances.size());
log.info("feign rule ---> serverName:{}, final server ip:{}:{}", instance.getServiceId(), instance.getHost(),instance.getPort());
return new DefaultResponse(instance);
}
}
}
@Configuration
@LoadBalancerClients(defaultConfiguration = CustomLoadBalancerConfiguration.class)
public class CustomLoadBalancerConfig {
}
@Configuration
class CustomLoadBalancerConfiguration {
/**
* 参考默认实现
* @see org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientConfiguration#reactorServiceInstanceLoadBalancer
* @return
*/
@Bean
public ReactorLoadBalancer reactorServiceInstanceLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new CustomRoundRobinLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
}
}
以上两部完成大功告成!
源码下载:https://github.com/dongweizhao/spring-cloud-example/tree/SR6-OpenFeign https://github.com/dongweizhao/spring-cloud-example/tree/EurekaOpenFeign
分享文章:解密SpringCloud微服务调用:如何轻松获取请求目标方的IP和端口
地址分享:http://www.36103.cn/qtweb/news14/30764.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联