微服务架构设计-4接口协议选择

确定了微服务的服务划分是关键的一步,接下来需要考虑选择合适的接口协议来实现微服务之间的数据通信。目前,主流的接口调用方式可以分为两大类:RPC(远程过程调用)和REST。

🔆 RPC(Remote Procedure Call): 以本地方法调用的形式处理远程方法调用的模型。常用的有:SOAP、RMI、Thrift、Avro、gRPC、Dubbo协议。
🔆 REST(Representational State Transfer):以资源为中心,描述资源状态变更的模型。常见于HTTP协议。

1. RPC

RPC是Bruce_Jay_Nelson在1984年的《Implementing Remote Procedure Calls》文章中首次提出的,用于构建简单、高效、通用的通信机制。以gRPC、Dubbo为代表的RPC方式的优点有:

  • 可定制协议/传输类型,可实现高性能通讯
  • 可用于强格式约束场景

使用RPC一般而言要先定义IDL(Interface description language,接口描述言),以gRPC为例,我们需要定义类似的proto文件:

// 定义服务名称
service Greeter {
  // 定义方法
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// 方法入参消息体
message HelloRequest {
  string name = 1;
}
// 方法出参消息体
message HelloReply {
  string message = 1;
}

对于Java而言,可以使用protobuf-maven-plugin 这一Maven插件将上述代码编译成Java文件,之后在服务端就可以实现对应的方法,如

private class GreeterImpl extends GreeterGrpc.GreeterImplBase {
  @Override
  public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
    HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
    responseObserver.onNext(reply);
    responseObserver.onCompleted();
  }
}

具体示例官方都有,这里不赘述,当然我们也可以使用不同的工具生成C++、NodeJS、C#、Go等不同的语言的实现。
由于Dubbo只支持JVM平台,所以它的IDL只要定义Java的接口即可。

我们可以看出RPC存在一些不足之处,包括以下方面:

  1. 多语言约束: 不同调用方之间存在语言约束。例如,跨语言RPC(如Thrift、Avro、gRPC)需要定义接口描述语言(IDL),而无需显式指定IDL的RPC(如Dubbo、RMI)对协议的参与方有语言限制。
  2. 字段变更导致重新部署: 当有新的服务调用方加入,需要重用某一接口并为其添加新字段时,通常需要修改IDL。大多数RPC框架要求所有调用方同步更新,这可能导致频繁的部署操作。

再看REST时,它主要基于HTTP协议实现,具有以下优点:

  1. 通用性高,无语言约束: REST具有较高的通用性,不受语言的限制。主流的编程语言都提供了对REST的良好支持。
  2. 弱格式约束,字段变更不需要重新部署: REST相对宽松的格式约束使得在接口字段发生变更时,不需要所有调用方都重新部署。这为系统的灵活性和演化提供了一定的便利。Dubbo需要版本控制,可以达到支持多版本并行的能力也算不错。
  3. 防火墙友好: 由于REST基于HTTP协议,而HTTP是广泛被接受的协议,因此REST更容易被防火墙接受。这使得在跨越网络边界时更容易实现通信。

2.REST

REST一般会基于Json或XML做为交互格式,两者均为跨语言、弱约束的格式。我们不需要先定义IDL再生成对应的语言文件,接口的变更除受影响的参与方需要修改外不需要全局重新部署,例如:

GET /user/{id}
{
  "name":""
}

这是我们的获取用户信息接口,返回用户姓名,有4个业务方调用,但后来有其中一个业务方要求再返回年龄信息,那么我们接口可以修改成:

GET /user/{id} 
{ 
"name":"", 
"age":0
}

这里增加了age字段只为某一业务方使用,其它业务方可以不用同步修改。在实际生产中我们一般会为核心接口增加版本号字段以更好地做多版本兼容。

为REST API添加版本有三种方式:

  • 版本信息放在Path或Query中,如
api.example.com/v1
api_v1.example.com
api.example.com/xxx?version=v1
  • 使用自定义Header, 如
Accept-Version:v1
Accept-Version:v2
  • 使用内容协商
Accept: application/vnd.example.v1+json
Accept: application/vnd.example+json;version=1.0

从REST设计的初衷而言,URL对于表述资源而与版本无关,因此纯学术的建议是使用第2、3种方式,但我们也看了大量第1种方式的API,其中不乏有知名的IT厂商,所以笔者觉得这3种都可以,如何选择完全看团队的风格。更多讨论

引入API版本控制后,确实可以在一定程度上提高接口的向下兼容性,允许更自由地进行业务修改。然而,多版本维护和兼容性确实会对服务架构提出更高的要求。
在实践中,对于服务逻辑变更较大的情况,发布一个新的服务版本是一种常见的策略。这种方式可以在保持向下兼容性的同时,为新的业务逻辑提供更大的灵活性。而对于变更相对有限的情况,可以考虑在服务中增加兼容/适配层,以平滑地过渡到新的版本。
对于REST的局限性,确实存在一些挑战。传输效率相对较低,因为REST通常使用文本格式(如JSON或XML),而不像一些RPC框架那样使用二进制协议,导致传输的数据量相对较大。此外,由于REST缺乏强约定规范,对字段和结构的修改可能会导致已接入调用方的异常。
总体而言,选择API版本控制策略和服务架构设计都需要根据具体情况和需求进行权衡。不同的项目可能会采用不同的方法,取决于团队的技术栈、发展阶段和对灵活性与稳定性的重视程度。

那么我们究竟如何选择呢?

在选择通信协议和架构模式时,需要综合考虑多个因素,包括性能、灵活性、维护成本等。下面以微服务架构为背景,对比REST(代表Spring Cloud)和RPC(代表Dubbo)的一些考虑因素:

  1. 性能: REST相对于RPC在IO性能上的一些损失。如果对于实际的业务调用场景而言,通信性能的差距可以被接受,并且可以通过缓存、压缩等手段进行优化,那么这可能不是一个决定性的因素。
  2. 异构系统的通讯: REST的无状态和基于标准协议的特性使其更容易与异构系统进行通信。如果系统中有多种语言和平台,REST可能更为方便。
  3. 接口修改的影响: 对于REST,确实需要通过一定的开发规范来防范接口修改可能带来的影响。这包括规范修改的方式,例如不允许删除或修改字段,而是使用新增字段来解决。
  4. 效率与锲约检查: 对于一些业务相对稳定、高频调用的服务,尤其是核心的公共服务,RPC可能更适合。RPC框架通常提供了强约定和类型检查,这有助于提高效率并防止一些潜在的错误。
  5. 兼容性和集成: 目前没有一种通用的框架同时支持REST和RPC。在微服务架构中,可以根据具体的业务需求和服务特性选择不同的通信方式,甚至可以混合使用。

针对车贷系统,考虑到整体并发要求不高,核心接口的 TPS 不会超过1000,选择REST作为通信协议是一个自然而合理的决定。REST在与异构系统通信以及保持接口灵活性方面具有优势,适合当前的业务需求。

但随着项目的后续版本迭代,将一些核心服务改成dubbo,以提升性能和稳定性。dubbo作为一种高效的RPC框架,可以在需要更高效通信的情况下发挥作用。这种逐步的演进方式允许在项目的不同阶段选择适合的通信方式,同时确保了对未来需求的灵活响应。

这样的决策考虑到了当前的业务需求和未来可能的性能提升需求,为系统架构的演进提供了一种合理的方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 229,406评论 6 538
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,034评论 3 423
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 177,413评论 0 382
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,449评论 1 316
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,165评论 6 410
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,559评论 1 325
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,606评论 3 444
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,781评论 0 289
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,327评论 1 335
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,084评论 3 356
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,278评论 1 371
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,849评论 5 362
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,495评论 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,927评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,172评论 1 291
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,010评论 3 396
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,241评论 2 375

推荐阅读更多精彩内容