SOA之 服务设计原则
Peng's Blog 只记录和技术相关的东西

SOA之 服务设计原则

2017-07-15
DAL
   

优化远程调用

​ 由于SO接口通常要被远程访问,而网络传输,对象序列化/反序列化等开销都远远超过本地Object访问几个数量级,所以要加快系统的响应速度、减少带宽占用和提高吞吐量,选择高性能的远程调用方式经常是很重要的。

以Java远程Service为例分析不同场景下,传输方式的某些可能较好选择:

  • 内网 + 同框架Java客户端 + 大并发:多路复用的TCP长连接 + kryo (二进制序列化) (kryo也可以用Protostuff,FST等代替)
  • 内网 + 不同框架Java客户端:TCP + Kryo
  • 内网 + Java客户端 + 2PC分布式事务:RMI/IIOP (TCP + 二进制)
  • 内网 + Java客户端 + 可靠异步调用:JMS + Kryo (TCP + 二进制)
  • 内网 + 不同语言客户端:thrift(TCP + 二进制序列化)
  • 外网 + 不同语言客户端 + 企业级特性:HTTP + WSDL + SOAP (文本)
  • 外网 + 兼顾浏览器、手机等客户端:HTTP + JSON (文本)
  • 外网 + 不同语言客户端 + 高性能:HTTP + ProtocolBuffer (二进制)

小结:从性能上来讲,tcp协议 + 二进制序列化更适合内网应用,

​ 从兼容性、简单性来说,http+文本系列化 更适合外网应用

HTTP+JSON适合SOA吗?

不适合,因为虽然这样降低了学习的门槛,但也显著地增加负压应用的开发量和出错可能性。

​ 安利 Thrift:Thrift是最初来自facebook的一套跨语言的service开发框架,thrift是比WebServices更简单高效的技术,是在SOA中对WebServices最具有替代性的技术之一。

消除冗余数据

​ 由于service的远程调用开销很高,所以在它的输入参数和返回结果中,要尽量避免携带当前业务用例所不需要的冗余的字段,来减少序列化和传输的开销。

​ 引入OO中常用的Data Transfer Object (DTO)模式,专门针对特定service的用例来定制要传输的数据字段。

粗粒度契约

​ 同样由于远程调用开销高,同时service的外部使用者对特定业务流程的了解也比不上组织内部的人,所以service的契约(接口)通常需要是粗粒度的,其中的一个操作就可能对应到一个完整的业务用例或者业务流程,这样既能减少远程调用次数,同时又降低学习成本和耦合度。

​ 而OO接口通常可以是非常细粒度的,提供最好的灵活性和重用性。

​ 例如,article service支持批量删除文章,OO接口中可以提供

deleteArticle(long id)

​ 供用户自己做循环调用(暂不考虑后端SQL之类优化),但SO接口中,则最好提供

deleteArticles(Set<Long> ids)

​ 供客户端调用,将可能的N次远程调用减少为一次。

通用契约

​ 由于service不假设用户的范围,所以一般要支持不同语言和平台的客户端。但各种语言和平台在功能丰富性上有很大差异,这就决定了服务契约必须取常见语言、平台以及序列化方式的最大公约数,才能保证service广泛兼容性。由此,服务契约中不能有某些语言才具备的高级特性,参数和返回值也必须是被广泛支持的较简单的数据类型(比如不能有对象循环引用)。

​ 如果原有的OO接口不能满足以上要求,则在此我们同样需要上述的Facade和DTO,将OO接口转换为通用的SO契约。

例如原有对象模型

class Foo {
   private Pattern regex;
}

Pattern是Java特有的预编译好的,可序列化的正则表达式(可提高性能),但在没有特定框架支持下,可能不好直接被其他语言识别,所以可添加DTO:

class FooDto {
   private String regex;
}

隔离变化

​ 虽然OO和SO都追求低耦合,但SO由于使用者范围极广,就要求了更高程度的低耦合性。

​ 隔离内外系统,把内部系统变化对外部的冲击减少到最小程度。

契约先行

​ Service是往往涉及不同组织之间的合作,而按照正常逻辑,两个组织之间合作的首要任务,就是先签订明确的契约,详细规定双方合作的内容,合作的形式等等,这样才能对双方形成强有力的约束和保障,同时大家的工作也能够并行不悖,不用相互等待。因此SOA中,最佳的实践方式也是契约先行,即先做契约的设计,可以有商务,管理和技术等不同方面的人员共同参与,并定义出相应的WSDL或者IDL,然后在开发的时候再通过工具自动生成目标语言的对应代码。

稳定和兼容

​ 在公开发布之后就要保证相当的稳定性,不能随便被重构,即使升级也要考虑尽可能的向下兼容性。

契约包装

​ 就像在通常应用中,我们要包装数据访问逻辑(OO中的DAO或者Repository模式),或者包装基础服务访问逻辑(OO中的Gateway模式)一样,在较理想的SOA设计中,我们也可以考虑包装远程service访问逻辑,由于没有恰当的名称,暂时称之为Delegate Service模式,它由消费端自己主导定义接口和参数类型,并将调用转发给真正的service客户端生成代码,从而对它的使用者完全屏蔽了服务契约,这些使用者甚至不知道这个服务到底是远程提供的的还是本地提供的。

OO&SO

​ 不能放弃面向对象,因为SO是有特定场景的,比如远程的、范围不定的客户端。所以它的设计原则不能被借来指导一般性的程序开发。OO经常需要提供细粒度接口和复杂参数类型以追求使用的灵活性和功能的强大性。

​ 理想架构蓝图(来自当当的架构师沈理)

SO+OO架构

参考资料

内容整理自:http://www.infoq.com/cn/articles/micro-soa-2?utm_source=infoq&utm_campaign=user_page&utm_medium=link


下一篇 Apache httpclient

Comments

评论功能暂停使用,如需跟作者讨论请联系底部的GitHub