Ray

Results 188 comments of Ray

可以看看有没有链接异常相关的error日志,比如Connection reset或者 Connect reset by peer之类的异常。motan是通过tcp的keepalive机制来保持链接有效的,如果是链接失效导致的异常,可以设置系统的tcp keepalive相关参数来调整tcp的探活频次,尽快感知到tcp链接失效的情况

Motan是长链接服务,**不适合**使用service别名进行负载均衡,建议使用ip进行服务发现。 getExistingReferer方法是为了复用已存在的referer,在小规模节点变化时不用重新建连所有server节点,这个方法是对比的server节点的url对象,server节点url中任何参数有变动都不再复用referer。 如果你们的场景必须使用service别名,可以参考[ConsulRegistry](https://github.com/weibocom/motan/blob/master/motan-registry-consul/src/main/java/com/weibo/api/motan/registry/consul/ConsulRegistry.java)自己实现一个定制的consul注册中心,在每次服务变更,[生成URL时](https://github.com/weibocom/motan/blob/fb3d60882624119e9c93fd6780a160a35a20be77/motan-registry-consul/src/main/java/com/weibo/api/motan/registry/consul/ConsulRegistry.java#L224)在URL参数中加入例如时间戳这种动态变化的参数,就会触发每次重新构建referer了。 实现SPI扩展可以参考[编写一个motan扩展](https://github.com/weibocom/motan/wiki/zh_developguide#编写一个motan扩展)

Motan的RpcContext是基于ThreadLocal机制,跨线程时需要自行透传对应的RpcContext,比如在生成异步执行的Runable任务时透传对应的RpcContext

CommonProxyFactory不是使用在动态代理场景的,是用来创建CommonClient或MeshClient,用在调用其他语言RPC或者[MotanMesh](https://github.com/weibocom/motan-go)的场景使用的。 这种场景下Java侧没有其他语言对应的service类,所以不能使用动态代理方式,需要使用client方式请求其他语言的RPC服务 CommonClient的使用方式可以参考Demo中的[Motan2RpcClient](https://github.com/weibocom/motan/blob/6aef3476fd340313eb94adf15fcd49a112e9ec7a/motan-demo/motan-demo-client/src/main/java/com/weibo/motan/demo/client/Motan2RpcClient.java#L62) MeshClient的使用方式可以参考Demo中的[DemoMeshClient](https://github.com/weibocom/motan/blob/master/motan-demo/motan-demo-client/src/main/java/com/weibo/motan/demo/client/DemoMeshClient.java)

`minWorkerThread`、`maxWorkerThread`这两个参数用来配置server侧的worker线程数量,需要根据服务端可以承载的压力(比如cpu load,请求耗时、对资源的读写压力等)来决定其数值,这块建议根据压力测试来找到适合的值。 关于这几个参数的配置建议: 1. server侧同步处理请求时(绝大部分业务是这种场景),需要使用worker线程完成整个server侧任务的执行,所以在server处理request期间会一直使用对应的worker线程,如果不是cpu密集型应用,这个worker数量(`maxWorkerThread`)可以适当加大,比如500以上(根据cpu能力和业务处理能力设置);如果是实现的react类型的异步server,比如[这个样例](https://github.com/weibocom/motan/blob/master/motan-demo/motan-demo-server/src/main/java/com/weibo/motan/demo/server/MotanDemoServiceAsyncImpl.java),由于worker线程只负责io相关事件处理,可以适当调小线程池。 2. `minWorkerThread`是预期最小worker线程数,建议设置为能够满足日常平均请求压力(QPS)的数值,比如100 4. `workerQueueSize`用来设置当worker线程数量不足时的等待队列长度,一般使用RPC都是对延迟比较敏感的场景,所以一般**不建议设置此参数**,即使用其默认值0不做等待,容量不足时直接快速失败。 5. 报错信息中的异常是命中了[默认的线程保护策略](https://github.com/weibocom/motan/blob/master/motan-core/src/main/java/com/weibo/api/motan/transport/DefaultProtectedStrategy.java),此策略可以避免某一个rpc方法调用突增时影响同RPC端口上的其他方法。如果业务场景比较简单,不需要进行额外的线程保护,可以在protocol中设置`providerProtectedStrategy="none"`

Motan的心跳是针对Endpoint(也就是Client)维度的,主要目的是为了解决因链路问题或者服务端压力(比如单节点连续失败10次)触发熔断后的恢复,服务正常的情况下是不会额外执行心跳操作的。 当client被熔断后,发送心跳会触发远程请求,只要请求成功就会恢复client的状态,所以心跳只需要检测client的状态就可以了。 至于单个channel维度的available,是由client内的连接池进行管理的,在获取或者交回链接时会进行单个链接的状态进行判断。

前面的回复提到了这个心跳机制是为了解决服务运行中,因链路问题导致熔断后,节点可以自动恢复,并不是用来解决启动时无效server节点的。 你提到的client启动时server节点未启动的问题是可以通过注册中心避免的,server端得先启动完成,并且打开提供服务的开关后,才会触发向注册中心注册server节点(一般server节点在启动后,还需要进行状态自检、预热等行为,保证服务可以正常工作后才会打开开关对外提供服务)。然后client端才能从注册中心发现这个server节点。

DirectRegistry是一个简单的注册中心实现,是为了方便直连调试等非线上场景,并没有做server节点可用性检测设计。如果direct注册中心要实现与其他注册中心等同的能力,需要在DirectRegistry中对serve节点的可用性进行周期性检测,在可用性发生变更时触发回调动态通知client当前可用的serve节点。这块我们会考虑在后续的版本中增强DirectRegistry。 一般线上业务不建议使用DirectRegistry这种服务发现方式,这种方式不太适合ip经常动态变动的云环境以及具有动态扩容能力的server。 server节点的不可用是可以发生在任何时刻的,client的熔断机制并不特别针对服务启动或者服务运行中,熔断机制是保证节点不可用后可以熔断,并在节点可用后可以恢复。链接可用性的管理是交给链接池负责的,如果请求时没有可用的链接,链接池会触发重新建连。 **熔断机制是处理偶发server节点不可用的意外场景的,如果经常会出现server节点不可用的情况,建议使用动态注册中心方式(例如zk),或者优化服务的运维流程**