feign自定义负载到指定ip

这篇具有很好参考价值的文章主要介绍了feign自定义负载到指定ip。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

项目背景:目前使用的springcloud微服务架构,开发人员本地联调过程中,会用到许多并非自己开发的微服务支持。但是这样就需要启动多个应用,严重影响开发效率。现在架构组讨论写一个feign重负载,可以指定一次请求负载到具体ip。

大致想法:重写feign的负载均衡客户端LoadBalancerFeignClient,每次请求会执行excute方法,在excute方法中获取指定ip,替换feign已经负载好的ip。

遇到问题:配置类没加getset方法,导致无法读取配置文件;DiscoveryClient获取服务列表用getApplication方法,之前用的getInstance获取不到;版本问题,10.7.4feign-core版本拿到的url是ip,需要将ip替换为applicationname,否则调用多个feignclient会报错,具体原因还没扒出来。

上代码:

 重写的负载客户端:

@Slf4j
public class FeignReBalancer extends LoadBalancerFeignClient {

    private Client delegate;
    private CachingSpringLoadBalancerFactory lbClientFactory;
    private SpringClientFactory clientFactory;
    private ReBalancerProperties reBalancerProperties;

    public FeignReBalancer(Client delegate,
                           CachingSpringLoadBalancerFactory lbClientFactory,
                           SpringClientFactory clientFactory, ReBalancerProperties reBalancerProperties, DiscoveryClient discoveryClient){
        super(delegate, lbClientFactory, clientFactory);
        this.delegate = delegate;
        this.lbClientFactory = lbClientFactory;
        this.clientFactory = clientFactory;
        this.reBalancerProperties = reBalancerProperties;
    }

    @Override
    public Response execute(Request request, Request.Options options) throws IOException {
        log.info("feign开始负载均衡...");
        //重新负载后的url
        String balanceUrl = null;
        //原始url
        String url = request.url();
        //应用名
        String applicationName = request.requestTemplate().feignTarget().name();
        balanceUrl = newURL(url,applicationName);
        URI uri = URI.create(url);
        //应用ip
        String clientName = uri.getHost();
        int port = uri.getPort();
        //发起请求客户端的IP
        String requestIp = PubFun.threadLocal.get()==null?null:PubFun.threadLocal.get().getClientIp();
        //获取注册中心的所有服务ip
        DiscoveryClient discoveryClient = SpringContextUtils.getBeanByClass(DiscoveryClient.class);
        Application application = discoveryClient.getApplication(applicationName.toUpperCase());
        List<InstanceInfo> instances = application.getInstances();
        //如果ip没有注册,则走默认
        if(!instances.stream().anyMatch(instance -> instance.getHostName().equals(requestIp))){
            if(reBalancerProperties.servers != null &&
                    reBalancerProperties.servers.keySet().stream().anyMatch(key -> key.equals(applicationName))){
                clientName = reBalancerProperties.servers.get(applicationName);
            }else{
            }
        }else{
            //ip在注册中心,则替换为传入的ip
            clientName = requestIp;
        }
        //设置负载服务
        List<Server> allServers = this.clientFactory.getLoadBalancer(clientName).getAllServers();
        String finalHost = clientName;
        //如果不存在ip的负载服务,则设置,存在不需要设置
        if(!allServers.stream().anyMatch(server -> finalHost.equals(server.getHost()))){
            this.clientFactory.getLoadBalancer(clientName).addServers(Arrays.asList(new Server(clientName, port),new Server(applicationName)));
        }
        Response response = this.getResponse(request, options, balanceUrl);
        log.info("feign自定义负载至:"+clientName+":"+port+"完毕!");
        return response;
    }



    private Response getResponse(Request request, Request.Options options, String newUrl) throws IOException {
        //重新构建 request 对象
        Request newRequest = Request.create(request.method(),
                newUrl, request.headers(), request.body(),
                request.charset());

        return super.execute(newRequest, options);
    }

    /**
     * 将ip替换
     * @param url
     * @param ipAddress
     * @return
     */
    private String newURL(String url,String ipAddress){
        String[] split = url.split("/");
        split[2] = ipAddress;
        return Arrays.stream(split).reduce((s1, s2) -> s1+"/"+s2).get();
    }

}

注入上面的负载客户端

@ConditionalOnProperty(prefix = ReBalancerProperties.prefix,name = "enable",havingValue = "true")
@Configuration
@EnableConfigurationProperties(value = {ReBalancerProperties.class})
public class ReBalancerConfiguration {

    @Bean
    public Client feignReBalancer(CachingSpringLoadBalancerFactory cachingFactory,
                                  SpringClientFactory clientFactory, @Autowired(required = false) DiscoveryClient discoveryClient, ReBalancerProperties reBalancerProperties) {

        return new FeignReBalancer(new Client.Default(null, null),
                cachingFactory, clientFactory, reBalancerProperties, discoveryClient);
    }
}

配置类:

@ConfigurationProperties(prefix = ReBalancerProperties.prefix)
@Data
public class ReBalancerProperties {
    static final String prefix = "rebalancer";

    public Map<String,String> servers;

    public String test;
}

补充:自己的负载client是在TraceFeignAspect切面类加载的文章来源地址https://www.toymoban.com/news/detail-410218.html

@Aspect
class TraceFeignAspect {
    private static final Log log = LogFactory.getLog(TraceFeignAspect.class);
    private final BeanFactory beanFactory;

    TraceFeignAspect(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    @Around("execution (* feign.Client.*(..)) && !within(is(FinalType))")
    public Object feignClientWasCalled(final ProceedingJoinPoint pjp) throws Throwable {
        Object bean = pjp.getTarget();
        Object wrappedBean = (new TraceFeignObjectWrapper(this.beanFactory)).wrap(bean);
        if (log.isDebugEnabled()) {
            log.debug("Executing feign client via TraceFeignAspect");
        }

        return bean != wrappedBean ? this.executeTraceFeignClient(bean, pjp) : pjp.proceed();
    }

    Object executeTraceFeignClient(Object bean, ProceedingJoinPoint pjp) throws IOException {
        Object[] args = pjp.getArgs();
        Request request = (Request)args[0];
        Request.Options options = (Request.Options)args[1];
        return ((Client)bean).execute(request, options);
    }
}

到了这里,关于feign自定义负载到指定ip的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 负载均衡-Feign

    1.1. 简介 feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。 Feign 和 Ribbon 的区别 1.Ribbon :是通过微服务的名字来调用微服务 2.feign : 是通过接口和注解来调用微服务 1.2. 作用 Feign 旨在使得编写 Java Http 客户端变得更容易 2.在前面

    2024年01月24日
    浏览(29)
  • Feign负载均衡写法

    Feign主要为了面向接口编程 feign是web service客户端,是接口实现的,而ribbon是通过微服务名字访问通过RestTemplate调用的,如下: 在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它(类似于以前Dao接口上标注Mapper注解,现在是一个微服务接口上面标注一个Fe

    2024年02月09日
    浏览(26)
  • SpringCloud学习—Feign负载均衡

    Feign是声明式Web Service客户端,它让微服务之间的调用变得更简单,类似controller调用service。SpringCloud集成了Ribbon和Eureka,可以使用Feigin提供负载均衡的http客户端 只需要创建一个接口,然后添加注解即可。使用接口方式调用服务 Feign,主要是社区版,大家都习惯面向接口编程。

    2024年02月15日
    浏览(32)
  • SpringCloud之 LoadBalancer和Feign负载均衡

    提示:以下是本篇文章正文内容,SpringCloud 系列学习将会持续更新 前面我们讲解了如何对服务进行拆分、如何通过 Eureka 服务器进行服务注册与发现,那么现在我们来看看,它的负载均衡到底是如何实现的,实际上之前演示的负载均衡是依靠 LoadBalancer 实现的。 在2020年前的

    2024年02月09日
    浏览(33)
  • 【SpringCloud Alibaba】Nacos服务管理与Feign负载均衡

    目录 一、微服务搭建 1.1 服务提供者与服务消费者 1.2 依赖关系   二、服务注册与负载均衡使用 2.1 Nacos 实现服务的注册与发现 2.2 Loadbalancer负载均衡、Feign声明式服务调用 2.3 示例综合实现 2.3.1 服务注册与发现测试 2.3.2 负载均衡测试  服务提供者 服务的被调用方(即:为其他微

    2024年02月03日
    浏览(37)
  • 【SpringCloud Alibaba】(四)使用 Feign 实现服务调用的负载均衡

    在上一文中,我们实现了服务的自动注册与发现功能。但是还存在一个很明显的问题:如果用户微服务和商品微服务在服务器上部署多份的话,之前的程序无法实现服务调用的负载均衡功能。 本文就带着大家一起实现服务调用的负载均衡功能 负载均衡:将原本由一台服务器

    2024年02月15日
    浏览(30)
  • Feign忽略Https的SSL最佳方案(且保证负载均衡将失效)

    同时解决Https的SSL证书验证问题和feign不支持Patch请求方法的问题 代码 1. 工具类 OkHttpUtils.java 代码 2. 工具类 FeignConfiguration.java

    2024年02月13日
    浏览(38)
  • 【项目实战】自定义设置Sonar的规则,要求DevOps工具链SonarQube只扫描指定模块

    开发微服务项目,很多会基于网络上现成开源的微服务框架进行二开,公司有单元测试覆盖率的要求,往往会使用SonarQube 来实现扫描代码的单元测试覆盖率,但是因为网络上现成开源的微服务框架很大部分是已经现成的代码,因此补充单元测试工作会很痛苦,于是,可以自定

    2024年02月14日
    浏览(37)
  • 微服务springcloud 06.feign框架,配合ribbon 负载均衡和重试,配合hystrix 降级,监控和熔断测试

    feign是ribbon +hystrix 的整合 01.新建 sp09-feign 项目 第一步: 第二步:选择依赖: pom.xml 需要添加 sp01-commons 依赖: 第三步:修改sp09-feign项目的application.yml 第四步:sp09-feign的主程序添加 @EnableDiscoveryClient 和 @EnableFeignClients 02.feign 声明式客户端 第一步:声明三个代理接口 这里的

    2024年02月10日
    浏览(40)
  • springcloud五大组件:Eureka:注册中心、Zuul:服务网关、Ribbon:负载均衡、Feign:服务调用、Hystix:熔断器

    Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。 SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。 Eureka包含两个组件:Eureka Server和Eure

    2024年04月10日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包