当看到gRPC、SOAP和REST时,它们都没有使用命名服务或注册表。我想知道为什么?使用注册表的优势是什么?它们使用什么替代方案?
RMI代表远程方法调用。它是一种面向对象的方法,只能调用对象上的方法。系统没有任何办法调用裸函数或“类方法”(也称为静态方法)。这是一个“纯面向对象”的方法。
但这意味着你需要一种方法来获取第一个对象引用,以便你可以开始调用方法并获得其他对象。这是通过注册表解决的。
gRPC和SOAP都是基于RPC风格的消息传递(仅数据;没有对象),可以类似于类方法地实现,只需选择不传递对象名称即可。REST在功能上与RPC非常相似,并传递数据。
REST有指向“对象”的“引用”,如https://example.com/orders/1234
,但您仍然可以调用https://example.com/orders
来获取订单列表。在RMI系统中,您需要获取对OrderManager
实例的引用,并查询其系统订单。
RMI(远程方法调用)类似于DCOM、CORBA、Android Binder和D-Bus。您可能会发现我在CloudNativeCon 2019上的演讲对此有所帮助。(我在演讲中使用Unix域套接字早些时候开始谈论了什么使引用特殊。)演讲的目标是帮助人们理解RMI与RPC之间的巨大差异。在通信系统中建模对象会显著改变系统,引入接口、强制类型转换检查和垃圾回收。在我看来,注册表是这些变化中最不重要的,尽管它是最明显的。
RMI注册表是一种在同一个Java(EE)服务器上公开多个独立服务的方法。这与例如在同一个gRPC服务器上部署多个gRPC服务(通过实现来自不同proto服务定义的多个不同存根)大致相似。
区别在于,在gRPC中,服务名称与proto文件的包结合起来自动成为给定服务实例的ID(例如,您不能在1个服务器上部署2个不同的gRPC服务实现)。类似地,在REST的情况下,资源路径是其在给定虚拟服务器内的ID。
另一方面,在RMI中,您可以在部署时为对象分配任何名称。因此,您需要一个实体将这些名称(通常通过JNDI)解析为特定的实现对象。
简而言之,gRPC服务或REST资源的名称/ID是由它们的定义隐含的,而在RMI中,这些事物是解耦的。
在您有多个实现相同接口的服务实例的情况下,这非常有用。
顺便说一下:RMI并不是这种设计的唯一示例:另一个示例是CORBA。