Unable to find instance for system-app
一、问题分析解决
技术栈: spring-cloud-gateway + nacos
在启动一个服务之后,到页面请求数据 出现 unable to find instance
翻译中文为找不到实例服务。如下图所示:
那么我们就该立刻想到是 nacos 注册中心或者是我们的服务注册到 nacos 时没配置好。
nacos 配置的检查没有问题,但是发现 nacos的服务注册一直无法上来,或者上来一会儿后,立马又掉线了。
那就可以肯定服务启动过程中一定有问题了。 打开后台日志,仔细观察服务启动日志,终于发现一个 大bug, outOfMemoryException for Metaspace . 查看 启动脚本, MetaspaceSize和MaxMetaspaceSize 都配置才 128M . 实在太小了, 改成 512M, 然后启动 问题解决了。
二、MetaspaceSize和MaxMetaspaceSize
-
JVM加载类的时候,需要记录类的元数据,这些数据会保存在一个单独的内存区域内,在Java 7里,这个空间被称为永久代(Permgen),在Java 8里,使用元空间(Metaspace)代替了永久代。永久代和元空间保存的数据并不完全一样,永久代中还保存另一些与类的元数据无关的杂项。
-
字符串对象在JVM中是如何存放的中说的,在Java 7里将字符串常量从永久代移动到了堆区域,但是永久代并没有完全改造完成。直到Java 8,永久代的改造才算完全搞定,在元空间中保存的数据比永久代中纯粹很多,就是类的元数据,这些信息只对编译期或JVM的运行时有用。
-
使用Java 8以后,关于元空间的JVM参数有两个:-XX:MetaspaceSize=N和-XX:MaxMetaspaceSize=N,对于64位JVM来说,元空间的默认初始大小是20.75MB,默认的元空间的最大值是无限。MaxMetaspaceSize用于设置metaspace区域的最大值,这个值可以通过mxbean中的MemoryPoolBean获取到,如果这个参数没有设置,那么就是通过mxbean拿到的最大值是-1,表示无穷大。
-
由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般我会将这两个值都设置为256M(PS:读者可以根据自己的实际情况再调整)。