SOA服务设计与实现的几个语言无关的原则速记

简介:

一、SOA定义

SOA即面向服务架构Service-Oriented Architecture。在SOA中一切皆服务。一个服务是通过消息交换来调用的程序一个信息系统是共同完成一个特定任务的一组服务SOA可以概述为一种由一组自治服务创建信息系统的方法。当然具体定义SOA真不好说反正不能简单理解为我们常用的开发技术如web服务、.net remoting或者wcf。

SOA设计四项基本原则

1. 边界必须明确

2. 服务必须自治

3. 服务分享 Schema 和 Contract, 而不是 Class

4. 由 Policy 决定服务间的兼容性

 

二、面向对象和面向服务

1、面向对象(OO)
a、应用于同一平台和运行环境

b、共享类型而不是Schema

c、采用便宜, 透明通信

d、对象的标识与生命周期由系统维护

e、客户机和服务器的同步的部署

f、容易概念化,因而提供一个自然的模型

g、一般不需要状态管理

h、应用于一个可预测的序列、期限和结果

i、目标是远程透明地使用方法和类型

 

2、面向服务(SO)
a、应用于异构平台和运行环境

b、共享Schema而不是类型

c、采用高成本, 明确通信

d、服务是自治的: 安全和失效是隔离

e、允许的连续, 分离部署客户机和服务器

f、基于软件组件和分布的对象依赖服务的协议

g、拥有并维护状态

h、基于消息, 异步的, 以及长通信

i、目标是提供服务隔离和调用的标准

 

三、SOA反模式

1、CRUD型接口

写应用的怎么能离得开CRUD但是CRUD型接口暴露在SOA服务中往往意味着服务抽象不合理这种类型接口带来的不良后果

a、鼓励类似 RPC 的调用行为


RPC示例

Serv.SendItemsToBePurchased(Array[] items);
Serv.ShippingAddress(stringAddress);
Serv.CheckOut();


消息示例

//Client
string msg= "<Items>...</Items>";
MyMethod(msg);
//Server
[WebMethod]
void MyMethod(stringmsg){ . . . }


b、可能隐含带会话状态的交互

c、交互可能过于繁复

小结CRUD型接口往往是抽象不合理的结果它弱化了Contract没有按业务功能来实现服务。有人说CRUD可以让调用方自己排列组合构造实现复杂服务但是这种接口往往需要调用多次而我们知道需要多个消息才能完成的操作是非常危险的因为它很容易造成业务数据不一致。

 

2、数据层接口

这种服务以数据驱动提供数据层DataTable、DataSet等重粒度的类型的返回说到底还是抽象不合理造成的。这种接口的不良后果

a、调用者隐性的依赖于你的服务的具体实现结果将是紧耦合

b、Contract 没有提供足够的信息来使用这个服务

 

四、SOA服务设计指南

如何设计一个容易使用的、定义明确的接口?总体来说你的接口必须
(1)、鼓励以文档为中心的思考特别提示: 如果你需要读一些别的文档才能调用现有接口那你的服务分解可能不正确
(2)、在 contract 中定义清晰的语义
(3)、通过对实现的封装达到松耦合
(4)、可以方便的从任何平台上调用 (WS-I base profile)
(5)、用一个完整的工作单元代表一个业务流程

 

想要真正设计实现一个容易使用定义明确的接口并不容易有几个经验可以指导我们的实际开发工作。

1、面向接口编程

服务接口抽象非常重要接口抽象的同时要定义契约定义schema接口一旦确定以后很难修改所以SOA接口抽象的好坏决定SOA服务的成败。

对于一般的SOA服务我们可以总结如下几种类型的接口

a、只读查询

b、只写 新增、修改和删除

c、读和写CRUD的组合

通常不论什么类型的接口输入参数不宜过多参数组合或依赖关系不能过分啰嗦复杂而对于返回信息则是越多越具体越好。

 

2、设计"大块头"的接口

服务必须封装一个完全的工作单元这种设计说明业务系统的实现细节被封装了不要指望调用方排列组合CRUD型接口正确完成一个业务功能。

SOA服务需要处理失败在一个服务内部必须要有完善的异常处理逻辑在任何情况下操作失败都不会将服务留在一个不一致的状态不能依赖于调用者调用另一个服务来修复错误。

a、服务的分解

• 以业务文档驱动的业务流程模型

• 不要试图使服务可扩展或灵活性
b、服务的自治性

• 任何事情都不要依赖于调用者

• 预期到调用者在使用你的服务时会犯错误

• 永远不要让服务处于一种不一致的状态

个人所接触过的某些SOA服务在实现的过程中从来没有考虑过接口因为CRUD惯了很多人认为原子的操作就是万能的接口。


3、避免共享分布式事务
对于大块头接口在一个长的流程中如何保持数据的一致性?这种情况下某些业务可能需要用到分布式事务。但是在SOA服务实现中应该避免分布式事务而应优先考虑Reservation 预约保留模式或者补偿机制。

Reservation 模式提供了最自治的保护Reservation 模式的好处

a、数据的一致性依赖于服务和它的业务规则

b、一致的处理失败情形 (超时通讯中断等)
Reservation 模式的问题

a、你必须为reservation定义业务规则 系统有变得更加复杂的风险

b、进度中工作项的隔离不会像二次提交的事务2PC那样自动化

当然我们还可以采用补偿方式但不要依赖于调用者来完成实在不能系统自动解决则人工介入。

 

4、保证幂等性

重复消息是SOA服务实现中非常常见的问题你永远不要指望调用方每次请求消息不一样对于读操作重复消息可能无害可对于写操作很可能就是灾难。Idempotent 幂等模式用于处理重复的消息非常合适。Idempotent 幂等模式的基本处理思路是

a、调用者给消息一个唯一请求 ID 标识

• 服务的Ccontract 可以说明这是必须的

• ID 标识一个工作单元这个工作单元只应执行一次

• 工作单元ID可以是Schema的一部分也可以是一个定制的SOAP Header

b、接收者在执行一个工作单元必须先检验该工作单元是否已经执行过。检查是否执行的逻辑通常是根据唯一请求 ID 在服务端查询请求是否有记录是否有对应的响应信息如果有直接把响应信息查询后返回如果没有那么就当做新请求去处理。

Idempotent 模式的好处

a、服务的自治性增强了不需要依赖于调用者作正确的事

Idempotent 模式的缺点

a、需要为缓存响应消耗大量的存储空间

b、需要为缓存管理付出性能的代价

 

5、避免共享Schema

一个很常见的问题对于多个服务应该用同样的 Schema还是每个服务定义自己的 Schema?

你可能会说服务实现后就非常稳定了应该很少改动。所以一个共享Schema搞定维护也只维护一份这样不是很爽吗

但是业务变化是永恒的主题服务也需要拥抱变化。你永远也不能保证服务实现不会变化也不能假设每次变化共享Schema只做增量永远向下兼容。

所以根据实际开发和维护经验最合理的做法是给每个服务定义自己的 Schema哪怕现有的Schema暂时都是一模一样的因为共享 Schema 使得独立变更每个服务比较困难并给服务的调用者带来不必要的麻烦。

Duplicate Is Evil但服务实现中应该避免假设适当重复这样应对变化才能更加游刃有余体会到这种好处需要开发认知能力提升到一定高度。

 

6、重视性能

需求即功能性能也是一项功能。对于开发人员没有人愿意自己开发的接口被人说性能差。我们应该在设计时就考虑性能在项目开发的整个过程中要对服务性能进行反复测试循序渐进改善系统性能。
主要有两种量化SOA服务性能的方法:

a、机器吞吐率 (requests/sec)

b、响应时间 (time to first/last bytes)

优化服务性能的方法通常有如下几种

a、减少本地数据IO尽量减少调用本地的web服务以减少网络IO

b、尽量使用原始数据类型参数避免在调用之间维护服务器状态

c、考虑对服务的结果进行缓存

d、要有批量多次的思路选择适用的大数据包传送方式或者对结果进行压缩

e、异步处理但会增加开发和维护难度。

 

7、其他

a、避免循环调用

服务之间相互引用或者几个服务之间隐式地构成闭环调用这种情况会引发无意识的递归造成系统崩溃。

b、重视安全性
服务调用的安全性也是一个问题。可以通过ESB实现服务注册、角色授权、权限分配等基本安全控制但是仍不能保证传输和调用安全性。可以采用一些技术解决方案增强安全性比如微软的WSE(Web Services Enhancements)。

 

参考

<<SOA服务设计原则>>

<<Understanding SOA with Web Services(中文版)>>

http://www.infoq.com/cn/news/2009/09/reservations






本文转自JeffWong博客园博客原文链接http://www.cnblogs.com/jeffwongishandsome/p/design-soa-service-principles-and-guidelines.html如需转载请自行联系原作者

目录
相关文章
|
5月前
|
前端开发 测试技术 人机交互
DDD - 理论到落地从统一语言开始
DDD - 理论到落地从统一语言开始
293 0
|
11月前
|
程序员
编程原则和模式
编程原则和模式
|
10月前
|
数据安全/隐私保护
如何把DDD应用到实际项目中来,例子中需要包含具体的领域模型设计,这么做的理由,以及一位这个设计而引进的坑
如何把DDD应用到实际项目中来,例子中需要包含具体的领域模型设计,这么做的理由,以及一位这个设计而引进的坑
131 4
|
5月前
|
设计模式 监控 算法
【领域驱动设计专题】一文带领你透视DDD领域驱动模型的本质和设计原理分析指南(通用语言体系)
【领域驱动设计专题】一文带领你透视DDD领域驱动模型的本质和设计原理分析指南(通用语言体系)
128 2
|
5月前
|
运维 前端开发 JavaScript
平台设计-概念澄清说明
平台所说模块一般指一个独立部署的前端项目
|
5月前
|
传感器 设计模式 测试技术
【软件设计师备考 专题 】程序设计的基础:模块划分的原则、方法和标准
【软件设计师备考 专题 】程序设计的基础:模块划分的原则、方法和标准
232 0
编程基本功:典型的柳氏风格命名一例
编程基本功:典型的柳氏风格命名一例
68 0
编程基本功:典型的柳氏风格命名一例
|
设计模式 开发框架 前端开发
设计概念的统一语言
设计概念的统一语言
|
测试技术
软件测试面试题:试述软件的概念和特点?软件复用的含义?构件包括哪些?
软件测试面试题:试述软件的概念和特点?软件复用的含义?构件包括哪些?
103 0
|
容器
框架设计思维符合语义即可使用,而不用关心底层的实现
框架设计思维符合语义即可使用,而不用关心底层的实现
222 0
框架设计思维符合语义即可使用,而不用关心底层的实现