Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【JRaft RheaKV】客户端使用rheaKVStore,最佳实践是随用随释放,还是进程启动后初始化一次?以及客户端在主切换时应如何处理? #1131

Closed
en-hui opened this issue Jul 23, 2024 · 28 comments

Comments

@en-hui
Copy link

en-hui commented Jul 23, 2024

Your question

Describe your question clearly

1、使用jraft-rheakv的时候,客户端的这个rheaKVStore,是初始化一次,保持内存中唯一就行,还是随用随释放?那种是最佳实践。

Your scenes

Describe your use scenes (why need this feature)

Your advice

Describe the advice or solution you'd like

Environment

  • SOFAJRaft version:
  • JVM version (e.g. java -version):
  • OS version (e.g. uname -a):
  • Maven version:
  • IDE version:
@en-hui en-hui changed the title [JRaft RheaKV] 客户端使用rheaKVStore,最佳实践是随用随释放,还是进程启动后初始化一次? 【JRaft RheaKV】客户端使用rheaKVStore,最佳实践是随用随释放,还是进程启动后初始化一次? Jul 23, 2024
@fengjiachun
Copy link
Contributor

Rheakv client 推荐保持单例使用

@en-hui
Copy link
Author

en-hui commented Jul 24, 2024

好的,感谢解答。

@en-hui en-hui closed this as completed Jul 24, 2024
@en-hui
Copy link
Author

en-hui commented Jul 25, 2024

@fengjiachun
大佬,我又遇到了一个问题,我模拟以下一种场景:
服务端启动了六台服务作为一个集群,三台普通节点,三台learner节点
客户端while(true) 调用rheaKVStore.bPutIfAbsent,每次间隔一秒钟。
我将leader挂掉,集群可以正常选择另外两台普通节点中的一个作为新的主,但客户端已经抛出异常,且看样子需要手动捕获并处理。

请问rheaKVStore作为客户端,不具备识别主切换的能力吗?我在while true里面不停重试,依然一直报错,看样子需要手动调用某些api才能解决。

我应该如何处理呢?

@en-hui en-hui reopened this Jul 25, 2024
@en-hui en-hui changed the title 【JRaft RheaKV】客户端使用rheaKVStore,最佳实践是随用随释放,还是进程启动后初始化一次? 【JRaft RheaKV】客户端使用rheaKVStore,最佳实践是随用随释放,还是进程启动后初始化一次?以及客户端在主切换时应如何处理? Jul 25, 2024
@fengjiachun
Copy link
Contributor

fengjiachun commented Jul 26, 2024

重试的逻辑看这里吧:

简单说,遇到一些指定错误,会发起重试(retries 上限是配置的),重试的时候,会强制刷新最新的 leader:

final boolean forceRefresh = ErrorsHelper.isInvalidPeer(lastCause);

重点:

重试次数有上限

次重点

文档确实少了点,先说抱歉,得需要你稍微看下代码,代码里面无秘密 :)

@en-hui
Copy link
Author

en-hui commented Jul 28, 2024

我再次尝试并简单看了一下逻辑,发现当主动停掉leader的时候,客户端未刷新元数据时,获取到的leader地址还是旧的。
然后在请求时会抛出com.alipay.remoting.exception.RemotingException: Create connection failed. The address is 127.0.0.1:8183异常,而此异常不会触发重试和刷新集群元数据。

这算是bug吗

看着逻辑像是只有请求通leader的一些异常情况才会触发刷新,如果leader直接挂了,请求不通的时候,没有重试机制?

@en-hui
Copy link
Author

en-hui commented Jul 28, 2024

是不是我可以这样调用,主动去刷新缓存中的元数据:
store.getPlacementDriverClient().getLeader(-1, true, 5000)

@fengjiachun
Copy link
Contributor

我再次尝试并简单看了一下逻辑,发现当主动停掉leader的时候,客户端未刷新元数据时,获取到的leader地址还是旧的。 然后在请求时会抛出com.alipay.remoting.exception.RemotingException: Create connection failed. The address is 127.0.0.1:8183异常,而此异常不会触发重试和刷新集群元数据。

这算是bug吗

看着逻辑像是只有请求通leader的一些异常情况才会触发刷新,如果leader直接挂了,请求不通的时候,没有重试机制?

感谢指出,是有这么个问题,我来看看处理下

@fengjiachun
Copy link
Contributor

是不是我可以这样调用,主动去刷新缓存中的元数据: store.getPlacementDriverClient().getLeader(-1, true, 5000)

嗯,是可以先这么处理

@en-hui
Copy link
Author

en-hui commented Jul 29, 2024

好的,您现在维护版本包括哪些,此问题会修复哪些版本?
我们用的是1.3.12版本

需要我提一个新的issue吗?

@fengjiachun
Copy link
Contributor

fengjiachun commented Jul 29, 2024

最近会发一个版本(1.3.15)来解决,不用新提 issue,这个 issue 不要关闭就行

@en-hui
Copy link
Author

en-hui commented Jul 29, 2024

分布式锁续约,如果遇到这种情况,直接把续约取消了?

那业务应该如何用锁,来避免这种情况呢。遇到主切换,岂不是会导致锁可能失效

@en-hui
Copy link
Author

en-hui commented Jul 29, 2024

使用store.getPlacementDriverClient().getLeader(-1, true, 5000)刷新后,确实在用store put get都可以成功了,但后台一直刷异常,是有什么后台任务也需要刷新url吗?应该如何刷,您帮忙看看

2024-07-29 14:41:23,013 [Bolt-heal-connection-thread] WARN com.alipay.sofa.common.log - reconnect target: Origin url [127.0.0.1:8181], Unique key [127.0.0.1:8181]. failed.
java.lang.RuntimeException: com.alipay.remoting.exception.RemotingException: Create connection failed. The address is 127.0.0.1:8181
at com.alipay.remoting.ReconnectManager$ReconnectTask.run(ReconnectManager.java:187)
at com.alipay.remoting.ReconnectManager$HealConnectionRunner.run(ReconnectManager.java:155)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.alipay.remoting.exception.RemotingException: Create connection failed. The address is 127.0.0.1:8181
at com.alipay.remoting.DefaultConnectionManager.create(DefaultConnectionManager.java:478)
at com.alipay.remoting.DefaultConnectionManager.doCreate(DefaultConnectionManager.java:781)
at com.alipay.remoting.DefaultConnectionManager.access$000(DefaultConnectionManager.java:51)
at com.alipay.remoting.DefaultConnectionManager$ConnectionPoolCall.call(DefaultConnectionManager.java:709)
at com.alipay.remoting.DefaultConnectionManager$ConnectionPoolCall.call(DefaultConnectionManager.java:675)
at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
at java.util.concurrent.FutureTask.run(FutureTask.java)
at com.alipay.remoting.util.RunStateRecordedFutureTask.run(RunStateRecordedFutureTask.java:39)
at com.alipay.remoting.DefaultConnectionManager.getConnectionPoolAndCreateIfAbsent(DefaultConnectionManager.java:567)
at com.alipay.remoting.DefaultConnectionManager.createConnectionAndHealIfNeed(DefaultConnectionManager.java:459)
at com.alipay.remoting.ReconnectManager$ReconnectTask.run(ReconnectManager.java:185)
... 2 more
Caused by: java.lang.Exception: Create connection to 127.0.0.1:8181 error!
at com.alipay.remoting.connection.AbstractConnectionFactory.doCreateConnection(AbstractConnectionFactory.java:329)
at com.alipay.remoting.connection.AbstractConnectionFactory.createConnection(AbstractConnectionFactory.java:185)
at com.alipay.remoting.DefaultConnectionManager.create(DefaultConnectionManager.java:475)
... 12 more
Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: /127.0.0.1:8181
Caused by: java.net.ConnectException: Connection refused
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:715)
at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:327)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:688)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514)
at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1044)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at java.lang.Thread.run(Thread.java:748)

@fengjiachun
Copy link
Contributor

看日志,不是 jraft 的,是 bolt rpc 有个健康监测在打印日志

@en-hui
Copy link
Author

en-hui commented Jul 29, 2024

看日志,不是 jraft 的,是 bolt rpc 有个健康监测在打印日志

那应该怎么做呢,一直刷屏日志。还有上面问的那个锁的问题

@en-hui
Copy link
Author

en-hui commented Jul 29, 2024

看日志,不是 jraft 的,是 bolt rpc 有个健康监测在打印日志

在jraft-core的BoltRpcClient.java的init(RpcOptions opts) 方法中,使用了this.rpcClient.enableReconnectSwitch();
这个会开启你说的那个重试,但是我还没找到如何关这个,且关了会有什么影响呢

@fengjiachun
Copy link
Contributor

分布式锁续约,如果遇到这种情况,直接把续约取消了?

keep lease 本就无法保证一定成功,但凡涉及到网络,任何操作都无法保证成功,如果续租失败,那么 lease timeout 超过后锁就不再生效

@fengjiachun
Copy link
Contributor

看日志,不是 jraft 的,是 bolt rpc 有个健康监测在打印日志

那应该怎么做呢,一直刷屏日志。还有上面问的那个锁的问题

bolt 的日志不是打在单独的文件里么

@fengjiachun
Copy link
Contributor

这个会开启你说的那个重试,但是我还没找到如何关这个,且关了会有什么影响呢

bolt 在创建连接的时候,如果网路有问题,有可能被 block 住最多一秒,所以需要它自动 reconnect,目前不支持修改 reconnect 的配置

@en-hui
Copy link
Author

en-hui commented Jul 29, 2024

这个会开启你说的那个重试,但是我还没找到如何关这个,且关了会有什么影响呢

bolt 在创建连接的时候,如果网路有问题,有可能被 block 住最多一秒,所以需要它自动 reconnect,目前不支持修改 reconnect 的配置

那这个无用的连接也不会取消,因为我已经刷新元数据了,获取到新的leader,对于原leader的连接我应该取消,让他不在reconnect,这个有方法吗

@en-hui
Copy link
Author

en-hui commented Jul 29, 2024

分布式锁续约,如果遇到这种情况,直接把续约取消了?

keep lease 本就无法保证一定成功,但凡涉及到网络,任何操作都无法保证成功,如果续租失败,那么 lease timeout 超过后锁就不再生效

感觉可以优化一下,对于一些连接问题,应该参照rheaKvStore,也有重试机制,尝试去新的leader进行续约。这个能优化吗。
不然这个续约功能,等于没有,不敢用这个功能

@fengjiachun
Copy link
Contributor

fengjiachun commented Jul 29, 2024

TODO:

@fengjiachun
Copy link
Contributor

分布式锁续约,如果遇到这种情况,直接把续约取消了?

keep lease 本就无法保证一定成功,但凡涉及到网络,任何操作都无法保证成功,如果续租失败,那么 lease timeout 超过后锁就不再生效

感觉可以优化一下,对于一些连接问题,应该参照rheaKvStore,也有重试机制,尝试去新的leader进行续约。这个能优化吗。 不然这个续约功能,等于没有,不敢用这个功能

都一样的,只要完成网络异常重试就可以了

@en-hui
Copy link
Author

en-hui commented Jul 29, 2024

异常重试当前好像是出错了立马重试?
是不是加一点缓冲时间比较好呢?加一个可配置化的重试间隔时间

@fengjiachun
Copy link
Contributor

异常重试当前好像是出错了立马重试? 是不是加一点缓冲时间比较好呢?加一个可配置化的重试间隔时间

不需要,跟你说的这个没关系,是刷新 leader 再重试,都不一定请求的同一个节点,间隔啥

@en-hui
Copy link
Author

en-hui commented Jul 30, 2024

异常重试当前好像是出错了立马重试? 是不是加一点缓冲时间比较好呢?加一个可配置化的重试间隔时间

不需要,跟你说的这个没关系,是刷新 leader 再重试,都不一定请求的同一个节点,间隔啥

好的,这个问题预计发版时间是啥时候呢,我可以参照pr先本地改一下先用着

@fengjiachun
Copy link
Contributor

应该这周会提一个 PR 来修复(最近较忙,我会尽快),发版预计再推迟一周

@fengjiachun
Copy link
Contributor

最新版本正准备发布,请关注 #1137

@fengjiachun
Copy link
Contributor

已发布 1.3.15,这个 issue 就关闭了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants