当前位置:首页 > 科技  > 软件

解密Spring Cloud微服务调用:如何轻松获取请求目标方的IP和端口

来源: 责编: 时间:2023-11-28 09:37:12 145观看
导读目的Spring Cloud 线上微服务实例都是2个起步,如果出问题后,在没有ELK等日志分析平台,如何确定调用到了目标服务的那个实例,以此来排查问题图片效果可以看到服务有几个实例是上线,并且最终调用了那个实例图片考虑到Spring

目的

Spring Cloud 线上微服务实例都是2个起步,如果出问题后,在没有ELK等日志分析平台,如何确定调用到了目标服务的那个实例,以此来排查问题Yjr28资讯网——每日最新资讯28at.com

图片图片Yjr28资讯网——每日最新资讯28at.com

效果

可以看到服务有几个实例是上线,并且最终调用了那个实例Yjr28资讯网——每日最新资讯28at.com

图片图片Yjr28资讯网——每日最新资讯28at.com

考虑到Spring Cloud在版本升级中使用了两种负载均衡实现,Robin和LoadBalancer,下面我们提供两种实现方案Yjr28资讯网——每日最新资讯28at.com

Robin实现方案

1. 技术栈

  • Spring Cloud: Hoxton.SR6
  • Spring Boot: 2.3.1.RELEASE
  • Spring-Cloud-Openfeign: 2.2.3.RELEASE

2. 继承RoundRobinRule,并重写choose方法

/** * 因为调用目标机器的时候,如果目标机器本身假死或者调用目标不通无法数据返回,那么feign无法打印目标机器。这种场景下我们需要在调用失败(目标机器没有返回)的时候也能把目标机器的ip打印出来,这种场景需要我们切入feign选择机器的逻辑,注入我们自己的调度策略(默认是roundrobin),在里面打印选择的机器即可。*/@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;    }}

3.修改RibbonClients配置

import org.springframework.cloudflix.ribbon.RibbonClients;import org.springframework.context.annotation.Configuration;/** * @description:feign 配置 */@Configuration@RibbonClients(defaultConfiguration = {FeignRule.class})public class FeignConfig {}

LoadBalancer实现方案

1. 技术栈

  • Spring Cloud: 2021.0.4
  • Spring Boot: 2.7.17
  • Spring-Cloud-Openfeign: 3.1.4

2. 继承ReactorServiceInstanceLoadBalancer,并实现相关方法

@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);        }    }}

3.修改LoadBalancerClients配置

@Configuration@LoadBalancerClients(defaultConfiguration = CustomLoadBalancerConfiguration.class)public class CustomLoadBalancerConfig {}@Configurationclass CustomLoadBalancerConfiguration {    /**     * 参考默认实现     * @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);    }}

以上两部完成大功告成!Yjr28资讯网——每日最新资讯28at.com

源码下载:https://github.com/dongweizhao/spring-cloud-example/tree/SR6-OpenFeign https://github.com/dongweizhao/spring-cloud-example/tree/EurekaOpenFeignYjr28资讯网——每日最新资讯28at.com

Yjr28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-34679-0.html解密Spring Cloud微服务调用:如何轻松获取请求目标方的IP和端口

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 超高效,使用Terraform创建Docker镜像和容器

下一篇: Javascript的闭包有哪些应用?你学会了吗?

标签:
  • 热门焦点
  • K60 Pro官方停产 第三方瞬间涨价

    K60 Pro官方停产 第三方瞬间涨价

    虽然没有官方宣布,但Redmi的一些高管也已经透露了,Redmi K60 Pro已经停产且不会补货,这一切都是为了即将到来的K60 Ultra铺路,属于厂家的正常操作。但有意思的是该机在停产之后
  • 6月安卓手机性能榜:vivo/iQOO霸占旗舰排行榜前三

    6月安卓手机性能榜:vivo/iQOO霸占旗舰排行榜前三

    2023年上半年已经正式过去了,我们也迎来了安兔兔V10版本,在新的骁龙8Gen3和天玑9300发布之前,性能榜的榜单大体会以骁龙8Gen2和天玑9200+为主,至于那颗3.36GHz的骁龙8Gen2领先
  • CSS单标签实现转转logo

    CSS单标签实现转转logo

    转转品牌升级后更新了全新的Logo,今天我们用纯CSS来实现转转的新Logo,为了有一定的挑战性,这里我们只使用一个标签实现,将最大化的使用CSS能力完成Logo的绘制与动画效果。新logo
  • 把LangChain跑起来的三个方法

    把LangChain跑起来的三个方法

    使用LangChain开发LLM应用时,需要机器进行GLM部署,好多同学第一步就被劝退了,那么如何绕过这个步骤先学习LLM模型的应用,对Langchain进行快速上手?本片讲解3个把LangChain跑起来
  • 微信语音大揭秘:为什么禁止转发?

    微信语音大揭秘:为什么禁止转发?

    大家好,我是你们的小米。今天,我要和大家聊一个有趣的话题:为什么微信语音不可以转发?这是一个我们经常在日常使用中遇到的问题,也是一个让很多人好奇的问题。让我们一起来揭开这
  • 2023年,我眼中的字节跳动

    2023年,我眼中的字节跳动

    此时此刻(2023年7月),字节跳动从未上市,也从未公布过任何官方的上市计划;但是这并不妨碍它成为中国最受关注的互联网公司之一。从2016-17年的抖音强势崛起,到2018年的&ldquo;头腾
  • 认真聊聊东方甄选:如何告别低垂的果实

    认真聊聊东方甄选:如何告别低垂的果实

    来源:山核桃作者:财经无忌爆火一年后,俞敏洪和他的东方甄选依旧是颇受外界关心的&ldquo;网红&rdquo;。7月5日至9日,为期5天的东方甄选&ldquo;甘肃行&rdquo;首次在自有App内直播,
  • 华为Mate 60系列用上可变灵动岛:正式版体验将会更出色

    华为Mate 60系列用上可变灵动岛:正式版体验将会更出色

    这段时间以来,关于华为新旗舰的爆料日渐密集。据此前多方爆料,今年华为将开始恢复一年双旗舰战略,除上半年推出的P60系列外,往年下半年的Mate系列也将
  • AI芯片初创公司Tenstorrent获三星和现代1亿美元投资

    AI芯片初创公司Tenstorrent获三星和现代1亿美元投资

    Tenstorrent是一家由芯片行业资深人士Jim Keller领导的加拿大初创公司,专注于开发人工智能芯片,该公司周三表示,已经从现代汽车集团和三星投资基金等
Top