- 环境
- 过程
- 代码
- 工具附件
- 尾语
- spring-boot --> 2.3.7
- spring-cloud --> Hoxton.SR9
- spring-cloud-alibaba --> 2.2.2.RELEASE
- 起因:本地开发时候,启动gateway与业务服务,当业务服务发生修改需要重启,gateway必须重启或等待服务定时刷新
- 操作:刷ribbon 与nacos服务列表更新源码,发现入口是写死的,无法重写,无法直接调用
- 风险:建议不要线上暴露,保留定时刷新原则,灰度发布也继续使用定时刷新,仅建议开发环境使用
依赖:
import cn.hutool.core.util.ReflectUtil; import com.alibaba.cloud.nacos.NacosServiceManager; import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.pojo.ServiceInfo; import com.alibaba.nacos.client.naming.core.HostReactor; import com.netflix.loadbalancer.ServerListUpdater; import com.netflix.loadbalancer.ZoneAwareLoadBalancer; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.context.named.NamedContextFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController;
方法:
public void refreshServerInfo() {
NamingService namingService = SpringUtil.getBean(NacosServiceManager.class).getNamingService(SpringUtil.getBean(Properties.class));
HostReactor hostReactor = (HostReactor) ReflectUtil.getFieldValue(namingService, "hostReactor");
Map serviceInfoMap = (Map) ReflectUtil.getFieldValue(hostReactor, "serviceInfoMap");
Set set = serviceInfoMap.keySet();
for (String serviceName : set) {
ReflectUtil.invoke(hostReactor, ReflectUtil.getMethod(HostReactor.class, "updateServiceNow", String.class, String.class), serviceName, "");
ZoneAwareLoadBalancer loadBalancer = (ZoneAwareLoadBalancer) SpringUtil.getBean(NamedContextFactory.class).getInstance(serviceName.replace("DEFAULT_GROUP@@", ""), ZoneAwareLoadBalancer.class);
ServerListUpdater.UpdateAction updateAction = (ServerListUpdater.UpdateAction) ReflectUtil.getFieldValue(loadBalancer, "updateAction");
updateAction.doUpdate();
}
}
工具附件
package com.*.*.gateway.util;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ArrayUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.ResolvableType;
import org.springframework.stereotype.Component;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.Map;
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
@SuppressWarnings("unchecked")
public static T getBean(String name) {
return (T) applicationContext.getBean(name);
}
public static T getBean(Class clazz) {
return applicationContext.getBean(clazz);
}
public static T getBean(String name, Class clazz) {
return applicationContext.getBean(name, clazz);
}
@SuppressWarnings("unchecked")
public static T getBean(TypeReference reference) {
final ParameterizedType parameterizedType = (ParameterizedType) reference.getType();
final Class rawType = (Class) parameterizedType.getRawType();
final Class>[] genericTypes = Arrays.stream(parameterizedType.getActualTypeArguments()).map(type -> (Class>) type).toArray(Class[]::new);
final String[] beanNames = applicationContext.getBeanNamesForType(ResolvableType.forClassWithGenerics(rawType, genericTypes));
return getBean(beanNames[0], rawType);
}
public static Map getBeansOfType(Class type) {
return applicationContext.getBeansOfType(type);
}
public static String[] getBeanNamesForType(Class> type) {
return applicationContext.getBeanNamesForType(type);
}
public static String getProperty(String key) {
return applicationContext.getEnvironment().getProperty(key);
}
public static String[] getActiveProfiles() {
return applicationContext.getEnvironment().getActiveProfiles();
}
public static String getActiveProfile() {
final String[] activeProfiles = getActiveProfiles();
return ArrayUtil.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
}
}
尾语
点个赞再走



