Spring Cloud 線上微服務(wù)實(shí)例都是2個(gè)起步,如果出問(wèn)題后,在沒(méi)有ELK等日志分析平臺(tái),如何確定調(diào)用到了目標(biāo)服務(wù)的那個(gè)實(shí)例,以此來(lái)排查問(wèn)題
圖片
可以看到服務(wù)有幾個(gè)實(shí)例是上線,并且最終調(diào)用了那個(gè)實(shí)例
圖片
考慮到Spring Cloud在版本升級(jí)中使用了兩種負(fù)載均衡實(shí)現(xiàn),Robin和LoadBalancer,下面我們提供兩種實(shí)現(xiàn)方案
/** * 因?yàn)檎{(diào)用目標(biāo)機(jī)器的時(shí)候,如果目標(biāo)機(jī)器本身假死或者調(diào)用目標(biāo)不通無(wú)法數(shù)據(jù)返回,那么feign無(wú)法打印目標(biāo)機(jī)器。這種場(chǎng)景下我們需要在調(diào)用失敗(目標(biāo)機(jī)器沒(méi)有返回)的時(shí)候也能把目標(biāo)機(jī)器的ip打印出來(lái),這種場(chǎng)景需要我們切入feign選擇機(jī)器的邏輯,注入我們自己的調(diào)度策略(默認(rèn)是roundrobin),在里面打印選擇的機(jī)器即可。*/@Slf4jpublic 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<Server> reachableServers = lb.getReachableServers(); List<Server> 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.cloudflix.ribbon.RibbonClients;import org.springframework.context.annotation.Configuration;/** * @description:feign 配置 */@Configuration@RibbonClients(defaultConfiguration = {FeignRule.class})public class FeignConfig {}
@Slf4jpublic class CustomRoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer { final AtomicInteger position; final String serviceId; ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider; public CustomRoundRobinLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) { this(serviceInstanceListSupplierProvider, serviceId, (new Random()).nextInt(1000)); } public CustomRoundRobinLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId, int seedPosition) { this.serviceId = serviceId; this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider; this.position = new AtomicInteger(seedPosition); } public Mono<Response<ServiceInstance>> choose(Request request) { ServiceInstanceListSupplier supplier = this.serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new); return supplier.get(request).next().map((serviceInstances) -> { return this.processInstanceResponse(supplier, serviceInstances); }); } private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier, List<ServiceInstance> serviceInstances) { Response<ServiceInstance> serviceInstanceResponse = this.getInstanceResponse(serviceInstances); if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) { ((SelectedInstanceCallback)supplier).selectedServiceInstance((ServiceInstance)serviceInstanceResponse.getServer()); } return serviceInstanceResponse; } private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> 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 {}@Configurationclass CustomLoadBalancerConfiguration { /** * 參考默認(rèn)實(shí)現(xiàn) * @see org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientConfiguration#reactorServiceInstanceLoadBalancer * @return */ @Bean public ReactorLoadBalancer<ServiceInstance> 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
本文鏈接:http://www.www897cc.com/showinfo-26-34679-0.html解密Spring Cloud微服務(wù)調(diào)用:如何輕松獲取請(qǐng)求目標(biāo)方的IP和端口
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com