1、Dubbo consumer端是线程安全的吗?

是的,不过这个答案是推理而来,不是直接读源代码得到的。因为Dubbo支持Spring Boot,Spring Boot是多线程模型,默认线程数是200,每个请求会在一个单独的线程处理,Dubbo的consumer端的实现是一个单例,如果这个单例不是线程安全的,则会在spring boot环境中发生严重的错误。所以推理的结果就是Dubbo consumer端是线程安全的。另外也可以推理出dubbo的provider必须是线程安全的,因为用户逻辑也是在一个单例中。

2、响应包会按照请求的时间顺序返回吗?

不会,假设客户端发送两个请求包,第一个是A第二个是B,因为负载均衡的原因,A和B分别发往两台不同的机器,这就会造成响应包乱序,即便是发往同一台机器,由于请求包是在一个线程池中处理两个请求很有可能是在两个不同的线程里处理的,这一样会造成响应包乱序。那么客户端时怎样响应包找到对应的请求,并恢复上下文呢?我们看dubbo的协议可以知道一个消息有消息头,消息头里有一个request id,这个id是64位的整型,服务器处理完数据后,会在响应包中写入请求id,这样客户端收到响应后就能根据这个id恢复上下文。或许有人会问,那么会不会因为这个request id申请地过快,导致同一时间内两个不同的请求拥有相同的id?要知道64整型的最大值非常地大,假如客户端一秒钟发送1亿次请求,那么也需要5848年才会分配出相同的id,一个请求是不可能有5848年这么长的生命周期的。那么如果request id是32位整形呢?32位整型在一秒1亿次请求环境下,每隔42秒就会生产出相同的request id,显然这样是非常不安全的。综上可以看出Dubbo的作者设计时是多么地深思熟虑。

3、在Dubbo中,是怎样唯一地确定一个服务的?

在Dubbo中,“服务接口+服务分组+服务版本”唯一地确定一个服务,同一个服务接口可以有不同的版本以便服务升级等,另外每个服务接口可以属于不同分组,所以当调用方消费服务时一定要设置正确的分组与版本。

4、为什么Dubbo在ZooKeeper为每个provider建立持久节点,而不是建立临时节点?

猜测:持久节点的特点是provider上线后会通知consumer,宕机则不会通知consumer,宕机的事实需要consumer自己探测到。如果是为provider建立临时节点,则意味着provider的上线下线情况由zookeeper来通知给consumer,如果provider和zk之间的会话超时时间比较长,比如30秒,那么consumer需要30秒后才能刷新provider列表,如果这30秒内consumer发送数据,通过超时机制其实只需几秒也可以很快找到宕机的provider。

5、如果所有provider都宕机了,consumer还能启动起来吗?

这取决于配置,dubbo:reference里有一个名为check的参数,默认值是true,当它为true时会检查是否有可用的provider,如果没有则启动会失败。