服务调用流程 服务调用异常请检查业务参数

导读:RPC , 微服务,Service Mesh这些服务之间的调用是什么原理?
作者 codedump codedump.info 博主,多年从事互联网服务器后台开发工作 。可访问作者博客阅读 codedump 更多文章 。
本文专注于演化过程中每一步的为什么(Why)和是什么(What)上面,尽量不在技术细节(How)上面做太多深入 。
服务的三要素
一般而言 , 一个网络服务包括以下的三个要素:

  • 地址:调用方根据地址访问到网络接口 。地址包括以下要素:IP地址、服务端口、服务协议(TCP、UDP , etc) 。
  • 协议格式:协议格式指的是该协议都有哪些字段,由接口提供者与协议调用者协商之后确定下来 。
  • 协议名称:或者叫协议类型,因为在同一个服务监听端口上面 , 可能同时提供多种接口服务于调用方,这时候需要协议类型(名称)来区分不同的网络接口 。
需要说明在服务地址中:
  • IP地址提供了在互联网上找到这台机器的凭证 。
  • 协议以及服务端口提供了在这台机器上找到提供服务的进程的凭证 。

服务调用流程 服务调用异常请检查业务参数

文章插图
这都属于TCPIP协议栈的知识点,不在这里深入详述 。
这里还需要对涉及到服务相关的一些名词做解释 。
  • 服务实例:服务对应的IP地址加端口的简称 。需要访问服务的时候 , 需要先寻址知道该服务每个运行实例的地址加端口,然后才能建立连接进行访问 。
  • 服务注册:某个服务实例宣称自己提供了哪些服务,即某个IP地址+端口都提供了哪些服务接口 。
  • 服务发现:调用方通过某种方式找到服务提供方,即知道服务运行的IP地址加端口 。
基于IP地址的调用
最初的网络服务,通过原始的IP地址暴露给调用者 。这种方式有以下的问题:
  • IP地址是难于记忆并且无意义的 。
  • 另外,从上面的服务三要素可以看到,IP地址其实是一个很底层的概念,直接对应了一台机器上的一个网络接口,如果直接使用IP地址进行寻址,更换机器就变的很麻烦 。
“尽量不使用过于底层的概念来提供服务”,是这个演化流程中的重要原则 , 好比在今天已经很少能够看到直接用汇编语言编写代码的场景了,取而代之的,就是越来越多的抽象,本文中就展现了服务调用这一领域在这个过程中的演进流程 。
在现在除非是测试阶段,否则已经不能直接以IP地址的形式将服务提供出去了 。
域名系统
前面的IP地址是给主机做为路由器寻址的数字型标识,并不好记忆 。此时产生了域名系统,与单纯提供IP地址相比,域名系统由于使用有意义的域名来标识服务,所以更容易记忆 。另外,还可以更改域名所对应的IP地址,这为变换机器提供了便利 。有了域名之后,调用方需要访问某个网络服务时 , 首先到域名地址服务中,根据DNS协议将域名解析为相应的IP地址,再根据返回的IP地址来访问服务 。
从这里可以看到,由于多了一步到域名地址服务查询映射IP地址的流程,所以多了一步解析,为了减少这一步带来的影响 , 调用方会缓存解析之后的结果 , 在一段时间内不过期,这样就省去了这一步查询的代价 。
协议的接收与解析
以上通过域名系统,已经解决了服务IP地址难以记忆的问题,下面来看协议格式解析方面的演进 。
一般而言,一个网络协议包括两部分:
  • 协议包头:这里存储协议的元信息(meta infomation),其中可能会包括协议类型、报体长度、协议格式等 。需要说明的是,包头一般为固定大?。?蛘哂忻魅返谋呓纾ㄈ鏗TTP协议中的\r\n结束符),否则无法知道包头何时结束 。
  • 协议包体:具体的协议内容 。
无论是HTTP协议,又或者是自定义的二进制网络协议,大体都由这两部分组成 。
服务调用流程 服务调用异常请检查业务参数

文章插图
由于很多时候不能一口气接收完毕客户端的协议数据,因此在接收协议数据时 , 一般采用状态机来做协议数据的接收:
服务调用流程 服务调用异常请检查业务参数

文章插图
接收完毕了网络数据,在协议解析方面却长期停滞不前 。一个协议 , 有多个字段(field),而这些不同的字段有不同的类型,简单的raw类型(如整型、字符串)还好说,但是遇到复杂的类型如字典、数组等就比较麻烦 。


推荐阅读