梦见你的名字 发表于 2023-10-18 10:15:34

研发提速: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文件中的自定义配置。
<em id="__mceDel"> 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 }</em>修改yml文件,主要是用来配置新增的自定义属性和小插件的开启和关闭。
建议手动在本地项目的yml文件添加属性,yml文件的配置,直接复制容易出现问题。
新增属性如下:
feign.dev.enabledfeign.dev.ipfeign.dev.portfeign.dev.namespaceidserver:
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 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 研发提速:nacos+openfeign环境下的本地链接服务