JVM排错
问题:网关Gateway过一段时间会很卡
问题排查:
步骤:
1)jps 查看进程号
2)jmap -heap pid 查看堆信息
查看jvm空间是否满,对象情况
3)jstack -l PID >1.txt 线程快照
jmap -dump:format=b,file=heapdump.phrof pid 生成堆转储快照dump文件(profilter需要的文件)
查看当前线程情况
发现:com.alibaba.nacos.client.naming.updater这个线程数量过多,上万个
问题定位:

通过swagger文档生成ios、android代码时,需调用网关接口根据路由获取所有的服务信息,重复调用了NamingFactory.createNamingService(properties)。
Flux<Route> routeFlux = routeLocator.getRoutes();
// 获取所有可用的host:serviceId
routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null).filter(route -> !self.equals(route.getUri().getHost())).subscribe(route -> {
// update-begin---author:zyf ---date:20220413 for:过滤掉无效路由,避免接口文档报错无法打开
boolean hasRoute = checkRoute(route.getId());
if (hasRoute) {
routeHosts.add(route.getUri().getHost());
}
// update-end---author:zyf ---date:20220413 for:过滤掉无效路由,避免接口文档报错无法打开
});
/**
* 检测nacos中是否有健康实例
*
* @param routeId
* @return
*/
private Boolean checkRoute(String routeId) {
Boolean hasRoute = false;
try {
// 修复使用带命名空间启动网关swagger看不到接口文档的问题
Properties properties = new Properties();
properties.setProperty("serverAddr", serverAddr);
if (namespace != null && !"".equals(namespace)) {
properties.setProperty("namespace", namespace);
}
NamingService naming = NamingFactory.createNamingService(properties);
List<Instance> list = naming.selectInstances(routeId, nacosGroupName,true);
if (ObjectUtil.isNotEmpty(list)) {
hasRoute = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return hasRoute;
}
在createNamingService过程中,nacos的HostReactor会创建线程池并启动名为com.alibaba.nacos.client.naming.updater的线程来更新服务信息,默认线程数为1~CPU核心数的一半。而HostReactor是通过new来获取对象的,所以每调用一次createNamingService都会创建一次线程池。最终导致每调一次生成代码,就会创建一次线程池。日积月累线程数就多了。



问题解决:
NamingService namingService = NamingFactory.createNamingService(properties);
将将创建的namingService作为一个springbean交个spring管理,这样只是在程序启动时创建了nacos命名空间一次。

浙公网安备 33010602011771号