成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

解密Spring Cloud微服務調用:如何輕松獲取請求目標方的IP和端口

開發 前端
Spring Cloud 線上微服務實例都是2個起步,如果出問題后,在沒有ELK等日志分析平臺,如何確定調用到了目標服務的那個實例,以此來排查問題。

目的

Spring Cloud 線上微服務實例都是2個起步,如果出問題后,在沒有ELK等日志分析平臺,如何確定調用到了目標服務的那個實例,以此來排查問題

圖片圖片

效果

可以看到服務有幾個實例是上線,并且最終調用了那個實例

圖片圖片

考慮到Spring Cloud在版本升級中使用了兩種負載均衡實現,Robin和LoadBalancer,下面我們提供兩種實現方案

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),在里面打印選擇的機器即可。
*/
@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<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.cloud.netflix.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,并實現相關方法

@Slf4j
public 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 {
}

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

以上兩部完成大功告成!

源碼下載:https://github.com/dongweizhao/spring-cloud-example/tree/SR6-OpenFeign https://github.com/dongweizhao/spring-cloud-example/tree/EurekaOpenFeign

責任編輯:武曉燕 來源: 架構成長指南
相關推薦

2020-06-30 07:58:39

微服務Spring BootCloud

2024-07-10 10:51:39

SpringEureka數據中心

2018-06-01 23:08:01

Spring Clou微服務服務器

2017-09-05 14:05:11

微服務spring clou路由

2023-12-19 09:33:40

微服務監控

2022-02-12 21:08:56

微服務SpringIstio

2018-05-23 15:58:27

Spring Clou微服務架構

2021-12-14 06:59:39

微服務Kubernetes架構

2024-02-06 18:05:54

微服務SpringCloud

2018-07-09 09:27:10

Spring Clou微服務架構

2024-08-05 10:03:53

2017-06-26 09:06:10

Spring Clou微服務架構

2017-12-20 15:37:39

Spring Clou微服務架構

2018-03-16 09:36:04

微服務Spring ClouDubbo

2017-09-04 16:15:44

服務網關架構

2023-03-20 08:00:00

公共云開發Spring Clo

2024-11-21 16:09:22

2023-10-12 09:48:00

微服務工具

2023-11-09 18:01:46

JavaSpring容器化

2017-12-01 08:54:18

SpringCloudHystrix
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 2018中文字幕第一页 | 91精品国产一区二区三区 | www.欧美视频 | 亚洲人精品| 亚洲综合伊人 | 欧美啊v在线观看 | 国产精品1 | 国产精品色哟哟网站 | 毛片区| 2021狠狠干| 国产91丝袜在线熟 | 久久91 | 中文字幕高清av | 精品亚洲一区二区三区 | 成人超碰| 最新中文字幕在线 | 亚洲午夜精品一区二区三区他趣 | 久夜精品 | 一区二区三区四区电影视频在线观看 | 欧美一二区 | 黄色在线免费观看视频网站 | 成人福利片 | 国产成人99久久亚洲综合精品 | 91在线精品播放 | 黄色大片毛片 | 久久久久久久久久久成人 | 亚洲成人天堂 | 国产福利91精品一区二区三区 | 精品在线一区 | 日韩波多野结衣 | 97精品国产97久久久久久免费 | 国产高清在线视频 | 日韩成人精品在线观看 | www性色 | 天天天操天天天干 | 国产欧美综合在线 | 国产精品一二三区在线观看 | 成人国内精品久久久久一区 | 亚洲福利片 | 色婷婷国产精品综合在线观看 | 黄视频免费在线 |