开源框架-SpringCloud系列方案spring cloud

Feign动态切换服务

2021-08-02  本文已影响0人  清蒸三文鱼_

概述

通过配置进行服务切换, 如果入参和出参一致, 那么代码几乎不用改动; 示例使用用户服务为例, 通过代理类进行切换qq或微信的用户服务

CODE

代理类UserServiceProxy( 入参出参通用 )

public interface UserServiceProxy {
    List<User> listUser(String name);
}

代理继承类

这里的入参出参尽量保持一致, 当然不一样也可以通过implements来特定实现; 下面的示例为了有所区分, url的地址不同

 public   interface QQ extends UserServiceProxy{
        @GetMapping("/openapi/v2/user/list")
        List<User> listUser(@RequestParam String name);
 }
 public interface Wechat extends UserServiceProxy{
        @GetMapping("/openapi/v1/user/listActive")
        List<User> listUser(@RequestParam String name);
    }

代理配置类ProxyConfiguration

因为@Condition类的注解和@FeinClient无法结合使用(会导致注入失败) , 所以需要自行管理FeignClient的bean

高版本(3.x+)

@Component
public class ProxyConfiguration {
    @Value("${user.service.qq.enable:false}")
    boolean enableQqService;
    @Autowired
    ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    public UserServiceProxy userProxy1(ApplicationContext context) {
        UserServiceProxy.QQ qq = new FeignClientBuilder(context)
                .forType(UserServiceProxy.QQ.class, "qqUser")
                .customize((ct) -> ct.contract(new SpringMvcContract())
                        .encoder(new SpringEncoder(messageConverters)).build()).build();

        UserServiceProxy.Wechat wechat = new FeignClientBuilder(context)
                .forType(UserServiceProxy.Wechat.class, "wechatUser")
                .customize((ct) -> ct.contract(new SpringMvcContract()).build()).build();
        return enableQqService ? qq : wechat;
    }
}

低版本(2.x+), 自定义Target

@Component
public class ProxyConfiguration {
    @Value("${user.service.qq.enable:false}")
    boolean enableQqService;
    @Autowired
    ObjectFactory<HttpMessageConverters> messageConverters;
    @Bean
    public UserServiceProxy userProxy2(@Autowired(required = false) ServiceInstanceChooser chooser) {
        CustomTarget<UserServiceProxy.QQ> qq = new CustomTarget<>(UserServiceProxy.QQ.class, "qq", "/qq_open/user", chooser);
        CustomTarget<UserServiceProxy.Wechat> wechat = new CustomTarget<>(UserServiceProxy.Wechat.class, "wechat", "/wechat_open/user", chooser);
        return enableQqService ?
                new Feign.Builder().contract(new SpringMvcContract()).encoder(new SpringEncoder(messageConverters)).target(qq) :
                new Feign.Builder().contract(new SpringMvcContract()).encoder(new SpringEncoder(messageConverters)).target(wechat);
    }

    static class CustomTarget<T> extends Target.HardCodedTarget<T> {
        private final ServiceInstanceChooser chooser;

        public CustomTarget(Class<T> type, String name, String url, ServiceInstanceChooser chooser) {
            super(type, name, url);
            this.chooser = chooser;
        }

        @Override
        public String url() {
            //使用chooser做负载均衡
            return chooser.choose(super.url()).getUri() + super.url();
        }
    }
}

POM

  <parent> 
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-parent</artifactId>  
    <version>2.5.3</version>  
    <relativePath/>  
  </parent>  

  <properties> 
    <java.version>1.8</java.version>  
    <spring-cloud.version>2020.0.3</spring-cloud.version> 
  </properties>  

  <dependencies> 
    <dependency> 
      <groupId>org.springframework.boot</groupId>  
      <artifactId>spring-boot-starter-web</artifactId> 
    </dependency>  
    <dependency> 
      <groupId>org.springframework.cloud</groupId>  
      <artifactId>spring-cloud-starter-openfeign</artifactId> 
    </dependency> 
  </dependencies> 

  <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
  </dependencyManagement>

运行

通过@Autowire UserServiceProxy进行方法调用, 能正确返回数据即切换成功

上一篇下一篇

猜你喜欢

热点阅读