当前位置:   article > 正文

微服务设计笔记(8)—— RPC 调用方式_微服务调用方式rpc

微服务调用方式rpc

RPC(Remote Procedure Call)—远程过程调用,它是一种不需要了解底层网络技术的协议,就可以通过网络,请求远程服务器上的服务。

我们可以调用本地的一个 RPC , 实际上,响应结果是由远程服务器返回的 。RPC 有很多种类型 , 比如 SOAP、Thrift、 protocol buffers 等等 )。不同的技术栈,可以通过其接口定义,很方便地生成客户端或服务端的桩代码 。

  • SOAP(Simple Object Access Protocol),即简单对象访问协议。它是交换数据的一种协议规范,是一种轻量的、简单的、基于XML的协议,它被设计成可在 WEB 上交换结构化或固化的信息。
  • Thrift 是一种接口描述语言和二进制通讯协议,它被用来定义和创建跨语言服务 。它是由 Facebook 为支持 “ 大规模跨语言服务” 而开发的 。
  • protocol buffer 是 google 的一个开源项目。它可串行化结构化的数据。就像 XML ,但它比 XML 更小 、 更快 、 也更简单 。 我们可以定义自己的数据结构,然后使用代码生成器所生成的代码来读写这个数据结构 。甚至可以在无需重新部署程序的情况下更新自定义的数据结构。

比如, 我们可以让一个 Java 服务对外表现为一个 SOAP 服务接口 , 调用方可以依据使用 WSDL( Web Service Definition Language,Web 服务描述语言 ) 接口定义内容,来生成基于 .NET 的客户端代码 。 这些技术都有一个共同点 , 那就是使用本地调用的方式和远程服务器进行交互。

Java RMI、 Thrift、 protocol buffers 是以二进制作为消息格式;而 SOAP 用的是 XML,而且绑定特定的网络协议(HTTP)。不同的网络协议,特性也不同。比如, TCP 协议能够保证消息送达对端;而 UDP 虽然会丢包,但开销较小。 所以我们可以根据实际应用场景来选择不同的技术栈

这些 RPC 实现一般会提供工具,快速生成服务端或客户端的桩代码 , 这样我们就可以直接开始编码 。

实际应用中,RPC 调用方式并没有那么好。一开始,问题还不那么明显 , 但慢慢就会暴露出来 , 其带来的负面影响要远远大于一开始快速编码所带来的好处。

(1)耦合

比如 Java RMI(Remote Method Invocation), 会导致服务端和客户端紧密耦合 , 因为双方都必须使用相同的 Java 技术栈。而 Thrift 和 protocol buffers 可以支持不同编程语言 , 从而在一定程度上缓解了这个问题 。

(2)远程调用的复杂性

RPC 的原意是隐藏远程调用的复杂性 。但远程调用特定涉及网络通信时间、对传输对象的序列化与反序列化,这样都会影响性能。

还有网络本身并不可靠。所以即使客户端和服务端都正常,也会因为网络问题,导致服务调用失败。还有黑客攻击情况也要予以考虑。

(3)脆弱性

假设我们使用 Java RMI 定义了一个服务接口:

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface CustomerRemote extends Remote {
    /**
     * 查找客户
     *
     * @param id
     * @return
     * @throws RemoteException
     */
    Customer find(String id) throws RemoteException;

    /**
     * 创建客户
     * @param firstname
     * @param surname
     * @param email
     * @return
     * @throws RemoteException
     */
    Customer create(String firstname, String surname, String email) throws RemoteException;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在这个接口定义中 , “创建客户” 方法,接受姓名及电子邮件作为入参 。 如果客户端希望只通过电子邮件就可以创建客户,我们可以在这个接口中,新定义一个方法 , 如下所示:

 Customer create( String email) throws RemoteException;
  • 1

因为重新定义了接口,所以所有的客户端都需要重新生成桩,即使某些客户端根本不需要这个新方法 。这是一个普遍现象,所以认为RPC 调用方式是脆弱的。

此外,还有一种形式的脆弱。 现在让我们来看看 Customer 对象:

import java.io.Serializable;

public class Customer implements Serializable {
    private String firstName;
    private String surName;
    private String email;
    private String age;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这里的 Customer 客户对象,除了之前在接口中所看到的 firstName、surName 和 age 之外,还定义了 age 属性。后来发现这个属性,完全没有任何客户端在使用它,是一个冗余字段。但不能直接在服务端删除它,因为会影响各个调用者的 Customer 客户对象,即使是基于二进制消息格式的 RPC 也存在同样的问题,即服务端和客户端无法实现部署分离。


如果一定要选用 RPC 调用方式,那么注意不要对远程调用过度抽象,让客户端留意网络调用的影响。还要确保我们可以独立地升级服务端接口,而不是强迫客户端升级。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/145737
推荐阅读
相关标签
  

闽ICP备14008679号