项目研发过程中,经常会遇到与测试人员工作重叠的情况,十分影响效率。
做了一个修改,可以在本地环境启动项目后和测试环境交互,并且不影响测试环境,理论上也可以用于线上环境的异常的快速处理。
准备事项如下:
一:搭建本地的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文件的配置,直接复制容易出现问题。
新增属性如下:- 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
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |