研发提速:nacos+openfeign环境下的本地链接服务

项目研发过程中,经常会遇到与测试人员工作重叠的情况,十分影响效率。

做了一个修改,可以在本地环境启动项目后和测试环境交互,并且不影响测试环境,理论上也可以用于线上环境的异常的快速处理。

准备事项如下:

一:搭建本地的nacos服务。

二:导入测试环境相应项目的nacos配置文件。

三:新增代码:

修改LoadBalancerFactory获取服务host的方式,由于是本地启动的项目,并且连接的还是本地的nacos,所以项目启动后,肯定不会注册到测试环境,相对的也获取不到测试环境的其他服务。

由于本人使用的时候是基于CachingSpringLoadBalancerFactory ,如果直接使用时不生效或者异常,可以DEBUG跟踪一下自己框架调用服务时使用的具体LoadBalancerFactory类。

  3 import cn.hutool.http.HttpUtil;   4 import com.alibaba.fastjson.JSON;   5 import com.alibaba.fastjson.JSONArray;   6 import com.alibaba.fastjson.JSONObject;   7 import com.netflix.client.config.IClientConfig;   8 import com.netflix.loadbalancer.ILoadBalancer;   9 import com.netflix.loadbalancer.Server;  10 import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;  11 import org.springframework.cloud.netflix.ribbon.ServerIntrospector;  12 import org.springframework.cloud.netflix.ribbon.SpringClientFactory;  13 import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;  14 import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;  15 import org.springframework.cloud.openfeign.ribbon.RetryableFeignLoadBalancer;  16 import org.springframework.util.ConcurrentReferenceHashMap;  17 import org.springframework.util.ObjectUtils;  18   19 import java.util.ArrayList;  20 import java.util.List;  21 import java.util.Map;  22   23 public class DevCachingSpringLoadBalancerFactory extends CachingSpringLoadBalancerFactory {  24   25     private volatile Map<String, FeignLoadBalancer> cache = new ConcurrentReferenceHashMap<>();  26     private volatile Map<String, List<Server>> server = new ConcurrentReferenceHashMap<>();  27     private volatile String ip;  28     private volatile String port;  29     private volatile String namespaceid;  30   31     public DevCachingSpringLoadBalancerFactory(SpringClientFactory factory) {  32         super(factory);  33     }  34   35     public DevCachingSpringLoadBalancerFactory(SpringClientFactory factory, LoadBalancedRetryFactory loadBalancedRetryPolicyFactory) {  36         super(factory, loadBalancedRetryPolicyFactory);  37     }  38   39     public boolean initialize(String ip,String port,String namespaceid) {  40         this.ip = ip;  41         this.port = port;  42         this.namespaceid = namespaceid;  43         return null != ip ? null != port ?  null != namespaceid ? true : false :false :false;  44     }  45   46     @Override  47     public FeignLoadBalancer create(String clientName) {  48         FeignLoadBalancer client = this.cache.get(clientName);  49         if (client != null) {  50             return client;  51         }  52         IClientConfig config = this.factory.getClientConfig(clientName);  53         ILoadBalancer lb = this.factory.getLoadBalancer(clientName);  54   55         //修改部分  56         List<Server> list = lb.getAllServers();  57         if (null == list || ObjectUtils.isEmpty(list)) list = new ArrayList<>();  58         list.addAll(Servers(clientName));  59         lb.addServers(list);  60   61         ServerIntrospector serverIntrospector = this.factory.getInstance(clientName,  62                 ServerIntrospector.class);  63         client = this.loadBalancedRetryFactory != null  64                 ? new RetryableFeignLoadBalancer(lb, config, serverIntrospector,  65                 this.loadBalancedRetryFactory)  66                 : new FeignLoadBalancer(lb, config, serverIntrospector);  67         this.cache.put(clientName, client);  68         return client;  69     }  70   71     /**  72      * 获取server  73      * 返回数组,重试机制交由原框架  74      * http://ip:port/nacos/v1/ns/instance/list?namespaceId=namespaceid&serviceName=client  75      */  76     public List<Server> Servers(String client) {  77         if(server.containsKey(client)) return server.get(client);  78         else synchronized (server) {  79             if(server.containsKey(client)) return server.get(client);  80             else {  81                 server.put(client,new ArrayList<Server>());  82                 String url = new StringBuilder("http://")  83                         .append(ip)  84                         .append(":")  85                         .append(port)  86                         .append("/nacos/v1/ns/instance/list?")  87                         .append("namespaceId=")  88                         .append(namespaceid)  89                         .append("&serviceName=")  90                         .append(client).toString();  91                 JSONObject jsonObject = JSON.parseObject(HttpUtil.get(url));  92                 JSONArray hosts = jsonObject.getJSONArray("hosts");  93                 for (int i = 0; i < hosts.size(); i++) {  94                     server.get(client).add(new Server(hosts.getJSONObject(i).getString("ip"),hosts.getJSONObject(i).getInteger("port")));  95                 }  96                 return server.get(client);  97             }  98         }  99     } 100  101 }

这个文件可以不用添加,主要是用来做一些其他的扩展。

 3 import feign.Client;  4 import feign.Request;  5 import feign.Response;  6 import org.springframework.cloud.netflix.ribbon.SpringClientFactory;  7 import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;  8 import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;  9  10 import java.io.IOException; 11  12 public class DevFeignClient extends LoadBalancerFeignClient{ 13  14     public DevFeignClient(Client delegate, CachingSpringLoadBalancerFactory lbClientFactory, SpringClientFactory clientFactory) { 15         super(delegate, lbClientFactory, clientFactory); 16     } 17  18     @Override 19     public Response execute(Request request, Request.Options options) throws IOException { 20         return super.execute(request, options); 21     } 22 }

配置文件用来替换原来IOC中的BEAN,另外用于获取后面yml文件中的自定义配置。

 3 import feign.Client;  4 import org.springframework.beans.factory.annotation.Value;  5 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;  6 import org.springframework.cloud.netflix.ribbon.SpringClientFactory;  7 import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;  8 import org.springframework.context.annotation.Bean;  9 import org.springframework.context.annotation.Configuration; 10  11 @Configuration 12 public class DevFeignConfig { 13  14     @ConditionalOnProperty("feign.dev.enabled") 15     @Configuration(proxyBeanMethods = false) 16     class DefaultFeignLoadBalancedConfiguration { 17         @Value("${feign.dev.ip}") 18         String ip; 19         @Value("${feign.dev.port}") 20         String port; 21         @Value("${feign.dev.namespaceid}") 22         String namespaceid; 23  24  25         @Bean 26         public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, DevCachingSpringLoadBalancerFactory devFactory, 27                                   SpringClientFactory clientFactory) { 28             System.out.println("#####################################进入本地调试模式#####################################"); 29             return new DevFeignClient(new Client.Default(null, null),null == devFactory?cachingFactory:devFactory, 30                     clientFactory); 31         } 32  33         @Bean 34         public DevCachingSpringLoadBalancerFactory devFactory(SpringClientFactory factory) { 35             DevCachingSpringLoadBalancerFactory devFactory = new DevCachingSpringLoadBalancerFactory(factory); 36             if(devFactory.initialize(ip,port,namespaceid)) return devFactory; 37             System.out.println("#####################################本地调试模式异常#####################################"); 38             System.out.println("feign.dev.ip " + ip); 39             System.out.println("feign.dev.port " + port); 40             System.out.println("feign.dev.namespaceid " + namespaceid); 41             System.out.println("#####################################本地调试模式异常#####################################"); 42             return null; 43         } 44     } 45  46  47 }

修改yml文件,主要是用来配置新增的自定义属性和小插件的开启和关闭。

建议手动在本地项目的yml文件添加属性,yml文件的配置,直接复制容易出现问题。

新增属性如下:

feign.dev.enabled
feign.dev.ip
feign.dev.port
feign.dev.namespaceid
server:   port: 服务端口号 spring:   application:     name: 服务名称   profiles:     active: dev   cloud:     nacos:       config:         file-extension: yml         namespace: 本地Nacos的命名空间       username: 本地Nacos的账号       password: 本地Nacos的密码       server-addr: 本地Nacos的IP:本地Nacos的端口号       discovery:         namespace: 本地Nacos的命名空间         group: DEFAULT_GROUP         enabled: true         register-enabled: true feign:   dev:     #true为开启本地调式,false为关闭     enabled: false     ip: 测试环境Nacos的IP     port: 测试环境Nacos的端口号     namespaceid:  测试环境Nacos的命名空间   client:     config:       default:         #不设置connectTimeout会导致readTimeout设置不生效         connectTimeout: 5000         readTimeout: 5000

 

发表评论

评论已关闭。

相关文章