1

像架构师一样来思考微服务接口设计

 2 years ago
source link: https://www.ttalk.im/2019/08/how-to-design-microservice-api.html?amp%3Butm_medium=Atom
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

随着微服务的兴起,在工作当中会涉及到很多接口互相调用的情况,本文从宏观上介绍了微 服的接口设计原则。

为什么做接口设计

我们在工作的时候一般都是面一个大型项目,随着微服务的兴起,不单单要设计模块之间的 接口,还要考虑各个微服务之间的接口。这篇文章就是针对如何去做微服务之间的接口设计 的思考。

如何做接口的设计

从笔者个人角度来说,可以从以下几个特性进行分析:

  1. 大规模系统和小规模系统
  2. 面向内部系统接口和面向外部系统的接口
  3. 大数据传输的接口和小数据传输的接口
  4. 长链接的接口和短链接的接口

很多时候我们优先考虑的是系统有多大,扩张性要有多好,对内还是对外以及我们有多大的 能力。很多时候这个东西并没有一个定论,更多是基于业务和团队人员组成而决定的。

接口的实施

不管接口是对内的还是对外的,我们都要做以下几件事情:

  1. 接口功能定义是否明确,是否有功能重复的地方
  2. 接口的升级机制,是否能兼容以前的数据
  3. 接口的数据量是多少,是否需要使用传输压缩机制
  4. 接口的熔断点在何处,何时该降级或停止服务
  5. 接口的安全机制是怎么样的,如何将非法调用隔离开来

这些事情是我们在开始设计和实现接口的时候,必须要先想到的。但是不要认为我们想到了 这些东西,我们就可以高枕无忧,然后事情就会像我们期待的那样发展下去。很多时候,接 口都会变成像阿米巴原虫一样,不是圆的而是不规则的多边形。

对内的接口

对内的接口简单说就是SOA,但是SOA也有很多种做法,例如常见的dubbo框架。在dubbo框架 下,我们所做的事情完全可以说是在dubbo框架下进行业务开发,并定义interface然后暴露 出去,我们此时貌似没有进行接口设计,但是实际上我们是完全按照dubbo的规范完成了接 口的定义,没错就是那个interface。看起来对内部的接口完全非常明确了,没什么可讲的, 但是其中还是有很多东西可讲的,我先讲讲我们常见的。

对服务发现的方案选择:

  1. 使用主动推送的方式,注册中心每次发生变化都会推送最新的列表给服务的使用者
  2. 使用被动拉取的方式,注册中心每次变化都保存好,然后使用者每次调用服务者的时候,先到注册中心查询一次

好了,让我分别来说说这两个方案

使用主动推送

可以让使用者很快的更新服务者信息,使用者调用服务者的时候只需要在本地的一个hash表 中查询一下即可,并且注册中心挂掉了之后,也不影响使用者调用服务者,看起来不错吧。 那么让我来说说这方案的弊端,首先要实现watch-notify机制,大概有人会说不是有 Zookeeper吗?自带该机制和数据冗余机制,那么我想说的是,当业务量起来的时候, Zookeeper的watch机制真的能顶住吗?接着是,服务者的负载均衡并不好处理。那么有没有 解决方法,这个可以参看dubbo中的注册中心是如何玩耍的。

使用被动拉取

这个好像很直观,但是每次都查询注册中心,这性能,注册中心能处理的了吗?大家不妨想 一下DNS服务器,其实该方案完全可以使用简单的内部DNS实现。那么该方案的好处不言而喻, 负载均衡好处理,并且非常简单。但是问题呢,性能和稳定性是要深入考虑的事情。

剩下的就是需要考虑的传输协议了,为什么要考虑传输协议?原因很简单:

  1. 接口平均传输的数据量和自己的内网带宽的平衡
  2. 是否要跨语言协作
  3. 是否侵入业务了

为何考虑带宽

虽然注册中心第一步解决了我们的快速扩张的问题,但是呢,内网带宽毕竟是有限的。随着 服务数量增多和调用量的增加,有时候我们会发现,同一个服务我们明明增加了N台部署响 应时间却下降了很多,按照公式应该响应时间不变的呀?这个时候,我们可能猛然看到监控 上我们的内网带宽已经跑满了。

为何考虑跨语言

难道一个公司不就是一种后端语言?其实不然,我曾见面试过一个公司,内部的业务之复杂, 语言使用之繁多。很多时候,我们需要站在一个公司发展的角度上考虑这个问题,而不是一 个纯技术的细节上考虑这个问题。

为什么要考虑是否侵入业务

不侵入业务,就是尽可能的封装底层的实现,让业务线更少的去考虑底层发生什么了。很多 人说,这对业务线的人不公平,阻碍了他们的技术发展。其实不然,让业务线的同仁们更多, 更深入的思考业务发展是非常重要的事情,我个人认为研发分两类,一类是玩算法和底层的, 另一类就是深入业务的,他们都有自己的长处和短处。其实减少业务的侵入是为了更快的实 现产品功能,让产品上线,让公司的业务快速迭代起来,这样对任何人都是有好处的。

这个与其说是升级,不如说是怎么做不同版本的数据共存和A/B测试。一般在很多成行的SOA 系统中,已经很完善了,我没必要在这里面多废话。但是还是要多说一句,数据多版本不易, 且升且小心。

对外接口,大家很快就会想到Restful。随着现在创业的兴起,应当说是智能手机和Web2.0 的兴起(更应该说的本质是,网络带宽变好,手机流量降价)。但是对外接口并不限于 Restful,还有大家不愿意谈的纯Socket接口。对外接口可讲的东西非常多,不过思路上基 本上和对内接口没太大的差别,所以我这里就主要讲下为什么选择纯Socket的接口。

我们不愿意面对的长链接,很多研发,甚至公司级别,都不愿意去尝试这个技术。原因嘛, 请看下面:

  1. 调试复杂,研发成本高
  2. 国内网络环境复杂,加重了第一条
  3. 国内用户对流量敏感,长链接心跳控制不好,容易被认为是偷流量
  4. 协议设计比较复杂,对研发的要求上升了很多

但是长链接真的就那么难嘛,其实不然。更多时候,是产品层面用不上,一般只有IM类型的 应用或者实时对战类的游戏才会选择长链接。当然偶尔我们也想提供一些高互动的交互,如 果只是在应用内短暂使用,完全可以选择websocket(不过面对中国强大的高铁和运营商基 础建设的规划TT)。

接口的保护

当我们面对很多外部接口的时候,我们需要考虑数据的安全性。为什么要考虑安全性:

  1. 包含用户数据
  2. 包含交易数据
  3. 以及甚至你不想让用户自己知道的数据

保护接口的方式最基本的是SSL/TLS,然后呢:

  1. 对称加密的方式
  2. 非对称加密的方式

先说下我们为什么要在SSL/TLS下面再次进行加密呢?大家可能听说过以色列一个网络安全 公司的事情了,换句话说一旦根证书被释放出去了,分分钟可以做SSL/TLS的man in middle 的攻击。同时有些稍微高级的用户,会针对你的接口进行刷接口的行为。

简单且易用。但是问题也明显,一旦秘钥泄漏或者被用户强猜出来了,那么影响还是很大的。

非对称加密的方式

实现略复杂,同样也面临第一种方式的问题。但是可以有一个专门的秘钥管理人员,生成公 钥和秘钥对后,将公钥交付给客户端,将秘钥交付给服务器端,大大减少了泄漏的可能性。 同时用户即便猜出了客户端的公钥,也无法解密别的用户提交的数据,而只能伪造请求。

机器在运行的时候,定期自动和秘钥管控中心进行秘钥交换,每台机器在交互的时候使用的 秘钥都不同。虽然可以带来一定的安全性,但是会给秘钥管理中心带来巨大的压力,同时调 试也比较麻烦。这种方式个人认为适合使用在,传统小交易量的行业中,例如说银行的ATM 机。

内部接口需要吗?

我们可以假定一个场景,服务者A有10个服务器,但是由于使用者B的算法错误,总是先选择 服务者A的某台服务器,那么我们可以想象到服务者A的某台服务器压力非常大,然后逐步的 就失去了响应,接着就会被认为被离线,接着使用者B又同样的方式打掉了第二台服务器。 带来的影响就是,轻者响应速度很慢,严重的就是整个系统雪崩性的逐个崩溃停止服务。

一般怎么做

不管对内部还是对外部,我们都可以选择使用漏桶和令牌桶等算法来保护接口。对外部,我 们还可以通过使用时间戳加整个URL整体签名技术来防止重放攻击和进行限流保护。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK