从我个人角度来说,可以从以下几个特性进行分析:
很多时候我们优先考虑的是系统有多大,扩张性要有多好,对内还是对外以及我们有多大的能力。很多时候这个东西并没有一个定论,更多是基于业务和团队人员组成而决定的。
一定要做的事情
不管接口是对内的还是对外的,我们都要做以下几件事情:
这些事情是我们在开始设计和实现接口的时候,必须要先想到的。但是不要认为我们想到了这些东西,我们就可以高枕无忧,然后事情就会像我们期待的那样发展下去。很多时候,接口都会变成像阿米巴原虫一样,不是圆的而是不规则的多边形。
对内的接口简单说就是 SOA,但是 SOA 也有很多种做法,例如常见的 dubbo 框架。在 dubbo 框架下,我们所做的事情完全可以说是在 dubbo 框架下进行业务开发,并定义 interface 然后暴露出去,我们此时貌似没有进行接口设计,但是实际上我们是完全按照 dubbo 的规范完成了接口的定义,没错就是那个 interface。看起来对内部的接口完全非常明确了,没什么可讲的,但是其中还是有很多东西可讲的,我先讲讲我们常见的。
对服务发现的方案选择:
好了,让我分别来说说这两个方案
可以让使用者很快的更新服务者信息,使用者调用服务者的时候只需要在本地的一个 hash 表中查询一下即可,并且注册中心挂掉了之后,也不影响使用者调用服务者,看起来不错吧。那么让我来说说这方案的弊端,首先要实现 watch - notify 机制,大概有人会说不是有 Zookeeper 吗?自带该机制和数据冗余机制,那么我想说的是,当业务量起来的时候,Zookeeper 的 watch 机制真的能顶住吗?接着是,服务者的负载均衡并不好处理。那么有没有解决方法,这个可以参看 dubbo 中的注册中心是如何玩耍的。
这个好像很直观,但是每次都查询注册中心,这性能,注册中心能处理的了吗?大家不妨想一下 DNS 服务器,其实该方案完全可以使用简单的内部 DNS 实现。那么该方案的好处不言而喻,负载均衡好处理,并且非常简单。但是问题呢,性能和稳定性是要深入考虑的事情。
剩下的就是需要考虑的传输协议了,为什么要考虑传输协议?原因很简单:
虽然注册中心第一步解决了我们的快速扩张的问题,但是呢,内网带宽毕竟是有限的。随着服务数量增多和调用量的增加,有时候我们会发现,同一个服务我们明明增加了 N 台部署响应时间却下降了很多,按照公式应该响应时间不变的呀?这个时候,我们可能猛然看到监控上我们的内网带宽已经跑满了。
难道一个公司不就是一种后端语言?其实不然,我曾见面试过一个公司,内部的业务之复杂,语言使用之繁多。很多时候,我们需要站在一个公司发展的角度上考虑这个问题,而不是一个纯技术的细节上考虑这个问题。
不侵入业务,就是尽可能的封装底层的实现,让业务线更少的去考虑底层发生什么了。很多人说,这对业务线的人不公平,阻碍了他们的技术发展。其实不然,让业务线的同仁们更多,更深入的思考业务发展是非常重要的事情,我个人认为研发分两类,一类是玩算法和底层的,另一类就是深入业务的,他们都有自己的长处和短处。其实减少业务的侵入是为了更快的实现产品功能,让产品上线,让公司的业务快速迭代起来,这样对任何人都是有好处的。
这个与其说是升级,不如说是怎么做不同版本的数据共存和 A/B 测试。一般在很多成行的 SOA 系统中,已经很完善了,我没必要在这里面多废话。但是还是要多说一句,数据多版本不易,且升且小心。
对外接口,大家很快就会想到 Restful。随着现在创业的兴起,应当说是智能手机和 Web2.0 的兴起(更应该说的本质是,网络带宽变好,手机流量降价)。但是对外接口并不限于 Restful,还有大家不愿意谈的纯 Socket 接口。对外接口可讲的东西非常多,不过思路上基本上和对内接口没太大的差别,所以我这里就主要讲下为什么选择纯 Socket 的接口。
我们不愿意面对的长链接,很多研发,甚至公司级别,都不愿意去尝试这个技术。原因嘛,请看下面:
但是长链接真的就那么难嘛,其实不然。更多时候,是产品层面用不上,一般只有 IM 类型的应用或者实时对战类的游戏才会选择长链接。当然偶尔我们也想提供一些高互动的交互,如果只是在应用内短暂使用,完全可以选择 websocket (不过面对中国强大的高铁和运营商基础建设的规划 TT )。
当我们面对很多外部接口的时候,我们需要考虑数据的安全性。为什么要考虑安全性:
保护接口的方式最基本的是 SSL/TLS,然后呢:
先说下我们为什么要在 SSL/TLS 下面再次进行加密呢?大家可能听说过以色列一个网络安全公司的事情了,换句话说一旦根证书被释放出去了,分分钟可以做 SSL/TLS 的 man in middle 的攻击。同时有些稍微高级的用户,会针对你的接口进行刷接口的行为。
简单且易用。但是问题也明显,一旦秘钥泄漏或者被用户强猜出来了,那么影响还是很大的。
实现略复杂,同样也面临第一种方式的问题。但是可以有一个专门的秘钥管理人员,生成公钥和秘钥对后,将公钥交付给客户端,将秘钥交付给服务器端,大大减少了泄漏的可能性。同时用户即便猜出了客户端的公钥,也无法解密别的用户提交的数据,而只能伪造请求。
机器在运行的时候,定期自动和秘钥管控中心进行秘钥交换,每台机器在交互的时候使用的秘钥都不同。虽然可以带来一定的安全性,但是会给秘钥管理中心带来巨大的压力,同时调试也比较麻烦。这种方式个人认为适合使用在,传统小交易量的行业中,例如说银行的 ATM 机。
我们可以假定一个场景,服务者 A 有 10 个服务器,但是由于使用者 B 的算法错误,总是先选择服务者 A 的某台服务器,那么我们可以想象到服务者 A 的某台服务器压力非常大,然后逐步的就失去了响应,接着就会被认为被离线,接着使用者 B 又同样的方式打掉了第二台服务器。带来的影响就是,轻者响应速度很慢,严重的就是整个系统雪崩性的逐个崩溃停止服务。
不管对内部还是对外部,我们都可以选择使用漏桶和令牌桶等算法来保护接口。对外部,我们还可以通过使用时间戳加整个 URL 整体签名技术来防止重放攻击和进行限流保护。
转载自TTalkIM
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.