【nacos】生产集群部署3个节点挂其中一个,整个nacos集群不可用

摘要查找

1. 心跳超时:Nacos 集群中的各个节点之间通过心跳机制进行通信和状态同步。如果某个节点无法及时响应心跳请求,其他节点可能会将其标记为不可用,从而导致整个集群不可用。确保网络连接正常,并检查节点之间的延迟和性能,以避免心跳超时问题。
2. 数据一致性:Nacos 集群中的节点需要保持数据的一致性。如果其中一个节点上的数据与其他节点不一致,可能会导致整个集群无法正常工作。此时,可以尝试使用 Nacos 提供的恢复机制,如手动执行数据同步或重新启动节点来恢复一致性。
3. 故障转移:Nacos 支持主备模式和多主模式的高可用配置。确保正确配置了节点的角色和相关参数,使得当一个节点故障时,其他节点能够接替其功能并继续提供服务。这样即使一个节点挂掉,整个 Nacos 集群仍然可用。
为了复现故障情况,可以尝试模拟节点故障,例如暂停节点上的 Nacos 进程、断开网络连接等。这将导致集群中的节点无法正常通信,从而产生类似于实际故障的情况。
请注意,在生产环境中进行故障复现可能会对服务产生影响。因此,请务必在非生产环境中进行测试,并确保备份和恢复机制可以及时生效以避免数据丢失或服务中断。

问题日志

ERROR 1 --- [  XNIO-1 task-2] c.f.icsa.cache.component.CacheOperate    : Get jedis from ableNodes error1 at IP:PORT :Could not get a resource since the pool is exhausted
...
com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: One record is expected, but the query result is multiple records
...
Caused by: java.net.SocketTimeoutException: timeout
 ERROR 1 --- [  XNIO-1 task-2] c....impl.XXUserInfoServiceImpl       : nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2
 ERROR 1 --- [  XNIO-1 task-2] c....cache.component.CacheOperate    : Get jedis from ableNodes error1 at IP:PORT :Could not get a resource since the pool is exhausted
 Exception in thread "com.alibaba.nacos.client.naming.updater" Exception in thread "Keep-Alive-Timer" java.lang.OutOfMemoryError: GC overhead limit exceeded
 	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.addConditionWaiter(AbstractQueuedSynchronizer.java:1855)
 	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2068)
 	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
 	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
 	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 	at java.lang.Thread.run(Thread.java:748)
 java.lang.OutOfMemoryError: GC overhead limit exceeded
 Exception in thread "Thread-10" java.lang.OutOfMemoryError: GC overhead limit exceeded
  ERROR 1 --- [  XNIO-1 task-4] c.f.icsa.cache.component.CacheOperate    : Get jedis from ableNodes error1 at IP:PORT :Could not get a resource since the pool is exhausted
  ERROR 1 --- [  XNIO-1 task-9] c.f.icsa.cache.component.CacheOperate    : Get jedis from ableNodes error1 at IP:PORT :Could not get a resource since the pool is exhausted
 java.io.EOFException
 	at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2681)
 	at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3156)
 	at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:863)
 	at java.io.ObjectInputStream.<init>(ObjectInputStream.java:358)

修复问题

具体问题具体分析,归咎于代码缺陷…,恰好缓冲失效导致,反序列化内存溢出…已处理恢复

流为关闭

IOUtils.closeQuietly((InputStream)ois);

import org.apache.commons.io.IOUtils;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ByteArrayOutputStream;

public class CacheSerializeUtil
{
    public static byte[] serialize(final Object object) {
        ObjectOutputStream oos = null;
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            return baos.toByteArray();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            IOUtils.closeQuietly((OutputStream)oos);
            IOUtils.closeQuietly((OutputStream)baos);
        }
        return null;
    }
    
    public static Object unserialize(final byte[] bytes) {
        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        try {
            if (bytes != null && bytes.length > 0) {
                bais = new ByteArrayInputStream(bytes);
                ois = new ObjectInputStream(bais);
                return ois.readObject();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            IOUtils.closeQuietly((InputStream)ois);
            IOUtils.closeQuietly((InputStream)bais);
        }
        return null;
    }
}

Nacos 客户端 Worker 异常的解析与处理

1. 异常介绍
在使用 Nacos 客户端时,有时候会遇到 com.alibaba.nacos.client.Worker 异常,该异常是由一个名为 mysql-cj-abandoned-co 的线程引起的。这种异常通常表明 Nacos 客户端与 MySQL 数据库的连接出现问题,导致连接被废弃。

2. 异常原因
在 Nacos 客户端中,数据库连接池是通过 [HikariCP]( 实现的。当连接池中的连接长时间未被使用时,就会被标记为废弃,这时会有一个线程负责关闭这些废弃连接,该线程的名称就是 mysql-cj-abandoned-co。如果在关闭废弃连接的过程中发生异常,就会抛出 com.alibaba.nacos.client.Worker 异常。

3. 解决方案
遇到 com.alibaba.nacos.client.Worker 异常时,需要分析具体的异常堆栈信息,找出引发异常的根本原因。根据我们的经验,常见的引发该异常的原因有:

数据库连接超时:Nacos 客户端默认的数据库连接超时时间为30秒,如果数据库连接超时,则会抛出异常。可以通过增加 db.num、db.url、db.user 和 db.password 这些配置项来解决连接超时的问题。

数据库连接数不足:如果 Nacos 客户端需要大量的数据库连接来处理请求,但数据库连接池中的连接数不够用,就会出现连接不足的情况。可以通过调整 db.connectionPoolNum 配置项来增加数据库连接池的大小。

MySQL 服务不可用:如果 MySQL 数据库服务不可用,或者由于网络问题无法连接到 MySQL 服务器,就会导致无法获取数据库连接,从而抛出异常。可以通过检查 MySQL 服务状态和网络连接状态来解决该问题。

参考查询

com.alibaba.nacos.client.Worker" Exception in thread "mysql-cj-abandoned-co
深入浅出 对象序列化EOF异常(java.io.EOFException)
JedisCluster:“由于池已耗尽而无法获取资源”和“等待空闲对象超时”

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

掘金者说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值