星期日, 06月 29th, 2008
SOA是可持续的战略,不是一次项目
常常听到如下关于SOA的说法:
- 我们完成了SOA化改造。
- 我们的SOA化,已近实现了80%。
- 这次项目是为了实现SOA化,因此要请有这方面经验的公司来实施。
- 从技术角度层面来说,我们达到了SOA化的目标。
- 这是我们最后一个SOA个项目
- 等等
如果这些话出自程序员,项目经理等人员,也是无所谓的;如果出自IT管理层的人员,哪就是一种可怕的想法了。因为他把SOA仅仅看作是一次项目了,而没有把它作为战略。这样的后果也是可以预见的,最终本次投资将会失败。
因此,建议那些准备实施SOA的公司,首先回答这个问题:SOA是贵公司的一个战略吗?
为什么要回答这个问题?
- 从SOA概念来看
关于什么是SOA,我有几篇文章,可以参考(《这些都不是SOA》,《ESB产品升级准备:SOA、ESB、JBI、SCA、OSGI概念再学习、再理解》,《SOA,想说爱你不容易》)。丛概念上可以看出,SOA不少技术问题,它是一种思想,一种架构,因而不可能通过一个项目就把这种思想或架构完全实现;思想也是会发展得,今天的思想在明天或许就会不适应。
- 从SOA目标来看
SOA的目标是解决业务敏捷性问题。如今,大环境复杂多变,任何一个公司都不敢说自己的业务就是这几个、自己的业务会一直不会变,很多企业,在很短的周期内,就会推出各类产品(特别是服务类企业,例如:银行、互联网企业等)。只有那些能够快速适应变化,主动寻求变化的企业才能够生存下来,发展起来,例如:会跳舞的大象IBM,IT行业最大的特色就是变化快、发展快,如果IBM的业务不能敏捷的适应这种变化,它还能跳舞吗?正因为IBM深刻理解了SOA的目标,因而它把SOA看作一种战略–可持续的战略。
- 从IT管理角度来看
对于IT主管,一定要确保本公司的IT战略是可持续的,不能今天一种想法,明天又看到什么好思想,就换了一种想法,或者换个主管,就彻底换了战略(这种做法,就像我们国内的城市建设,路总是修不好)。既然从一种思路切合到了SOA领域,那么再次切换的成本将会更高,也不可能多种思路同时进行(吃得多,嚼不烂)。此外,谁能保证一次项目就确保几年内业务变化的需要?从我们实施的经验来看,必须持续的进行SOA化,才能确保SOA持续的发挥效果。
- 从系统分析角度来看
每次项目都要进行系统分析,都是基于当前的业务进行,那么不可避免的就会有一些盲点(从认知的角度看,人不可能一次就抓住事物的本质,何况大多数系统分析员不具有这种能力)和不合理支出。这些问题,只有在实施后一段时间才能发现(我们自己的实践经验);此外随着补丁的实施,原有的系统已经恶化,和最初的SOA化目标越来越远。此时,如果不能再次用SOA的思想重新审视系统,就将彻底失去了SOA带来的好处。
- 从技术特征来看
SOA非但不能让系统架构变得简单,反而变得复杂了(系统设计要求变高了、系统部署复杂了、发布复杂了、各类SOA相关技术的引入增加了对人员的要求),这也是为什么要引入SOA治理。从这一点来看,只有持续的SOA化,才能最终发挥SOA技术架构的好处。
再次提醒将要进行SOA化的朋友和已经进行了SOA化的朋友,把SOA当作贵公司的可持续的战略来看,而不要认为它紧紧是一次项目。
星期五, 06月 27th, 2008
SOA实践之:Java服务接口设计的一些实践准则
在SOA领域,一些OO领域的接口设计原则具有很好的借鉴意义,但随着SOA化带来的分布式特性,有些东西就需要进行特殊处理。下面就我们进行SOA化过程中接口设计过程中,曾经比较容易出现过问题的地方进行部分总结。
【术语说明】
服务与业务组件的定义:
- 业务组件:最小的业务逻辑单元,例如:密码验证组件、登录组件。
- 服务:业务模块提供给外部的核心业务逻辑,服务组合业务组件。例如:修改密码服务,会使用密码组件的验证服务,也会使用登录组件的修改密码服务。
【说明:】可否密码验证组件的功能合并到登录组件哪?可以的,此处之所以单独分离,与我们提供多种密码验证机制有关,登录组件对应的业务并未完全涵盖密码验证组件的功能。
- 服务接口的方法,禁止重名(overload特性)。大多数序列化工具【例如:XFire】对重名方法进行处理时,都不可能避免的存在或多或少的问题。为了减少麻烦,还是放弃OO的这一特性,或者在面向服务领域,重载本身就不是一个特性。
- 服务接口的方法,避免返回异常【我们是禁止异常,包括业务异常、系统异常】。这个要求看起来违反了一些对象设计的原则,从实际使用角度来看,具有如下好处:很多工具对异常序列化很容易出现错误;一不小心,外部使用者还会产生异常依赖;需要外部使用者自己把异常翻译为业务语义【从业务角度来说不是件好事情】。
- 服务接口必须有清晰的文档说明,对于常量性质的参数,要列出支持的常量值。
- 服务接口尽可能把查询和业务方法分离【非必须】。好处是使用AOP时简单方便,对于查询方法进行特殊处理时也比较方便,例如:与cache整合、与搜索引擎整合、与特殊权限要求进行整合(例如,对返回信息按照权限进行过滤)等。
- 服务接口参数排列按照如下原则:操作主体对象或ID,业务参数{…},环境参数。
例如:verifyPassword(String operatorId, String password, ServiceContext serviceContext)
operatorId是操作主体的ID。
Password是密码。
serviceContext是环境参数。
- 业务处理类接口,返回值可以采用统一对象模式。例如:ServiceResult:
public class ServiceResult<T> implements Serializable {
private static final long serialVersionUID = 760567785564620157L;
private boolean isSuccess;
private String resultCode;
private T resultObject;
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
public String getResultCode() {
return resultCode;
}
public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}
public T getResultObject() {
return resultObject;
}
public void setResultObject(T resultObject) {
this.resultObject = resultObject;
}
}
采用这种模式,实际是按照协议的角度进行设计,所有服务按照统一的包装模式返回。
-
服务接口的参数避免使用Object类型,集合类型要指定具体对象类型。原因:当使用Object时,使用者获取到WSDL文件时,不知道该传递什么业务数据,如果是其它语言的调用者,更无法理解了;这类接口设计违反了业务SOA的原则,暗含着如下潜台词:业务上不明确的,不清晰的。
- 服务接口避免使用集合类型,尽可能使用数组类型。
- 服务接口中使用枚举的原则:如果是对外界发布,避免使用枚举;如果使用者众多,避免使用枚举;如果是内部几个专用系统使用,可以考虑使用枚举,可以参考《枚举产生的系统耦合性》。【文档的清晰化,可以化解常量参数不明确的问题】
- 服务接口避免设计成面向数据的操作,例如:updateStatus。这类接口,通常包含太多的业务含义,甚至没有业务含义,需要外部使用者去理解业务内部的细节,否则无法进行操作。这也是我们设计服务接口时,需要特别注意的地方,不要让外部使用理解业务内部是如何存储的,结构是什么样的,这样会导致业务耦合度过高,服务内部发生重构,变化时,外部使用也需要进行变化。
- 服务接口层建议设计一个统一的模板框架,来处理性能分析、特殊参数处理(例如:ServiceContext)、事务处理、异常处理、日志处理、事件处理、审计处理等具有共性的行为。
- 服务接口的方法名避免以:is,get开头,用find,check等来代替之,避免Java序列化工具把该类当作Java Bean进行处理。
- 业务组件中异常的要求:所有的业务组件,如果发现违法业务原则的地方,需要中断程序的执行,那么throw统一业务异常,该业务异常可以借鉴如下方式设计:
public class ComponentException extends Exception {
private static final long serialVersionUID = -6900280471536579015L;
private ErrorCodeEnum code = null;
public ComponentException ErrorCodeEnum code) {
super();
this.code = code;
}
public ComponentException ErrorCodeEnum code, Throwable e) {
super(e);
this.code = code;
}
public ErrorCodeEnum getCode() {
return code;
}
public void setCode(ErrorCodeEnum code) {
this.code = code;
}
}
坏处:从异常名看不出明确的业务语义。
好处:避免服务层需要捕获多种异常;业务语义通过ErrorCodeEnum返回到业务层。
- 业务组件内部尽可能少的进行事务处理【除非有特殊的需求】、异常处理【除外业务组件自身组合了外部的业务服务,此时需要处理异常】。
好处:统一由服务层进行处理,可以避免事务处理的错误。不进行异常处理,可以避免异常转义时,出现信息丢失;此外,如果使用了统一异常,那么就更不能在业务组件内部进行异常处理了,否则会发生原始业务限制规则被丢失的可能。
对于一些基本原则,可以参考《SOA实践之:在程序层,面向服务的设计准则探讨》一文。
使用方,推荐使用代理模式来使用外部服务。
1、可以进行一些特殊处理,例如:网络异常处理,远程性能评估等
2、对内部提供重业务层面的方法,屏蔽环境参数
3、外部服务接口发生变化时,或许修改一处就能够满足变化
4、如果要对传输层、安全进行定制时,会非常方便
【参考资料】
模块分解原理的探索
Interface Design — Best Practices in Object-Oriented API Design in Java
Part 1: Exploring the development, interfaces, and operation semantics of services
Part 2: Exploring the development, interfaces, and operation semantics of services
星期四, 06月 19th, 2008
SOA架构之性能解决策略之一【引入Cache过程的思考点】
采用SOA架构实现了业务的分离、重用、对BPM的支持。经过初步的测试,这种架构不能满足性能的要求【前提:SQL已经优化,数据库cache已经不能满足需求】,就当前的应用环境来看,引入cache是解决性能的一个办法,这也是比较通用的一个方案。
目前网上已经有大量的cache实现,介绍cache原理,cache使用案例的资料。下面就我在使用过程中的一些思考点分享一下。
1. 在SOA系统架构的那一层进行cache

系统架构如图所示:可以在1、2、3、4、5每个点考虑增加cache。
在1这个位置采用cache,通常采用Apache相关的cache扩展。
在2、3、4这些位置采用cache,可以使用本地cache,或者远程cache。例如:ehcache、Memcached等。
在5这个位置,可以通过增加服务器内存,调整数据库cache;或者通过数据库伸缩性实现性能提升。可参考该文《大型网站的架构设计问题—-大型高并发高负载网站的系统架构 》【主要讲了MySpace的用户量不断增长过程中,如何逐步提高性能】或相关数据库的性能提升方案。
在2这个位置,可以缓存web页面,业务数据对象等。
在3这个位置,可以缓存业务数据对象、服务相关配置信息、路由规则、消息数据等。
在4这个位置,可以实现通用数据访问层,实现统一数据源查询,业务数据对象可以缓存起来,例如《ebay的架构中的DAL层》。【这一层同时能够为分库,多数据源系统,提供统一数据访问能力。】
具体在那一层实施cache以提高性能,需要依据自身系统的特点来实施。以内容为主的系统,考虑在1,2处采用cache;也业务为主的系统,考虑位置2、3、4、5处采用cache;采用SOA架构的业务,考虑位置3、4、5处采用cache【如果数据库存在切分,多源的情况,可适当倾向位置3,4】。我依据自己的需要,选择了如下一个方案。

2. 资源重复利用的频率【命中率】
之所以要采用cache,目的就是要提供资源重复利用率,减少数据库访问。因此先要评估使用cache能否达到目的【例如:提供性能】,如果命中率太低,需要考虑别的方案;如果批量查询很多,命中率又很低,可考虑放弃部分即时性,用搜索引擎等方案。
3. Cache产品选型
在Java平台,对于内存cache,可以选择Map系列,Ehcache,OsCache等;远程cache,分为中央模式,例如Memcached等;Cluster模式,例如:JBoss Cache等。具体使用那个cache,要依据:缓存什么,性能要求,数据量,可伸缩性(例如1个月之后,就需要加服务器了),事务要求,过期特性,一致性要求等来选择。
我的这个案例:性能要求高;能缓存60%的情况下命中率已经很高;数据量很大,但增长慢;随时需要增加服务器,以增加缓存的数据;不需要考虑事务,业务处理时,直接使用数据库锁,也即允许部分查询脏数据;按照数据特点,分别采用不同的过期时间;一致性要求高。因此选择了Memcached。
【资料:】
了解cache基本知识,java cache产品的一些特性,可以参考《Cache Insight》
一篇关于cache选择的文章《Cache的选择以及特性建议》
一篇关于远程cache的文章《Remote Cache, Transaction》
一篇关于分页情况下,cache使用策略《分页 & QueryKey & 预取》
我选择了Memcached作为远程cahce,推荐大家去官方网站看看。
4. 资源如何在cache中存储、资源粒度的选择
在cache存储的资源粒度,首先依据cache资源的特点,例如登录者基本信息,就完全可以一次性缓存起来,对于聚合关系结构的业务对象,在缓存的时候需要考虑业务特点,如果业务上对聚合对象内部的对象访问就很频繁,那么就考虑选择小对象力度缓存,否则考虑大粒度对象。第二点是cache自身的特点,本地JVM cache,可以考虑存储大对象,因为此时没有网络访问、数据流量的考虑,那么即使业务上小对象访问比较多,也可以考虑完全缓存整个对象关系;如果是远程cache,那么就要依据大粒度和小粒度对象访问的频率,然后决定。
【注】:查询返回的集合对象,不适合在cache中存放。
对象关系过于庞大时,也不适合完全存放在cache中。
资源序列化:在使用远程cache的时候,需要考虑对象序列化的问题。
- 如果是Java序列化,那么资源对象内部,不要包含非数据类对象,例如服务类,Logger等。
- 资源对象内部的数据属性如果使用了Long,Integer,Enum(包括自定义枚举)等非原子类型的对象,需要考虑序列化定制【如果资源量比较小,cache服务器资源足够多,可以延后考虑,但不能不考虑】。原因是对象序列化,会导致序列化后的二进制数据偏大,特别是Enum类型要引起关注【可参考《服务化的行军中:Enum使用,快乐的痛苦》一文】。
- Hessian,XML序列化同样存在上面存在的问题。
key的规划。坚持如下几个原则:尽可能用外部可以提供的属性作为key;作为Key的属性,尽量避免重复的业务上的重复,例如:多个业务用同一个业务语义作为Key;Key之间存在关系,但多个Key指向同一个业务对象,此时只选择其中一个与对象直接cache,其它key与这个Keycache;Key如果能够按照某种规则推算出来,切勿cache。
【注:】远程cache情况下,同一个对象中存在静态数据和动态数据时,当cache的时候,可以分别建立cache【特别是对于一个关系复杂的大对象,意义更大】。
5. 资源过期策略
缓存在cache中的对要要可以采用一定的过期策略,例如:某个对象缓存10分钟,因为它在10分钟之内还是能够被重复利用的;有些对象无限期缓存,因为它会被长期使用,此时对象是否被从cache中清除,由cache算法负责;最简单的方法是,不设置过期时间,由算法清楚,最终剩下的数据最有可能是重复率最高的。如果担心数据一致性的问题,那么可以依据业务对象特点,分配不同的过期时间。
6. 资源一致性解决方案
使用cache,最麻烦的是解决一致性问题,特别是对于业务系统,这种要求更高。
最简单的方式是:资源发生变化,就从cache中删除。
第二个问题是资源锁的问题,在存在并发的情况下,服务端必须锁定资源,如果不是带锁的cache,此时就要避免从cache中获取数据,以免脏数据。
注意:在多层cache的情况下,还需要考虑cache之间数据的一致性,而不仅仅是cache与数据库的一致性。
7. 每台服务器Cache的数据量评估
JVM内存cache要缓存多少数据,依据服务器内存【如果同时采用了本地文件缓存策略,就需要考虑准备在硬盘上钝化多少缓存数据】,cache对象的大小进行评估。远程cache能够缓存多少数据,依据内存【如果同时采用了本地文件缓存策略,就需要考虑准备在硬盘上钝化多少缓存数据】,cache对象的大小进行评估。
要进行评估,首先要计算出资源的尺寸【按照选择的序列化方式测量】。
计算每台服务器能够cache多少数据或需要cache多少数据才能够发挥cache的效果。在多机器环境下,对于JVM本地cache基本按照内存能容纳多少数据即可,如果同时开启了文件存储特性,可以按照资源活跃度来来粗略估计,在后期再依赖cache监控获得的数据进行精确调整。在远程环境下,如果采用单服务器模式,可以按照完全内存缓存的情况进行计算;对于cluster cache,目前还没有使用过,建议初期采用全内存方式进行计算。
8. 网络流量评估
在远程环境下必须评估网络流量/秒,以供SA参考。
9. Cache效能监控日志
在使用过中,会随时调整一些cache相关的参数,此时性能日志就非常重要。可以从2个层面获取日志:cache服务器自身的性能监控日志;业务系统定制的一些日志参数。
业务定制监控参数的一个简单例子:资源类型,会话数(Session ID),cache请求次数,cache命中次数,当前cache中数据量,数据库访问次数,平均访问时间。
10. Cache可用性监控
对于远程cache模式,需要提供相应的监控方案和通知方案。
11. 远程Cache可用性测试
考虑如下故障模式,是否对应用系统产生致命影响【主要是性能】:
- 本地cache不能正常使用
- 远程cache全部不能访问
- 其中1个cache服务器不能访问
- cache都不能工作时的性能指标等
12. 故障模式解决方案
Cache服务器故障时的解决方案,在确保系统可用的情况下,可以实施那些策略来度过难关。例如: 通过apache限制访问量。
13. Java环境,Cache如何与程序结合
在Java环境,可以通过如下方式实现结合:
- AOP方法拦截方式
- 面向属性方式
- Cache模板方式
- AOP扩展点方式
- 事件模式
- 代理模式
- 直接访问cache API
- 等
我选择代理模式实现查询和监控,事件模式实现数据更新。
14. 适度调整程序,以最优化cache效果
大部分情况,我们加入cache对应用层【相对于soa服务层】的影响很小。但某些时候,应用层的某些程序设计方式,数据获取方式,与cache结合的时候,可能会很不爽,甚至会导致成本过高。此时,不要死守某些所谓的原则,可以针对使用cache这种需要,适度调整程序,甚至某些业务的表现方式【只要业务本质不发生变化,程序上甚至可以违背某些API的原则—这些原则有时候,并未考虑特殊的cache使用需求】,以最优化cache效果。
【其它资料:】
Java开源缓存框架
使用Cache Farms和Read Pools提高Web应用的伸缩性
服务器的大用户量的承载方案 Nginx Squid Apache PHP MySQL
Declarative Caching Services for Spring
Spring Aop cache
youtube architecture
Golden rule of web caching
术语:性能、可伸缩性定义
Oracle’s Cameron Purdy Looks at 10 Patterns for Scaling Out — 该文虽然讲的是可伸缩性,但其中很多点也适用于性能思考过程,例如:“10 - Understanding the Problem,9 - Define the Requirements,4a - Plan for Overload,3a - Plan for Failure,2 - Tier Where It Makes Sense,1 - Simplify ”
可伸缩性最佳实践──来自eBay的经验—文中一条规则“适当地使用缓存”很重要,并不是每个业务点或架构层都适合使用缓存。
Trading Consistency for Scalability in Distributed Architectures —- 一致性与可伸缩性
利用 ThreadLocal 提高可伸缩性
Memcached使用点滴
星期六, 06月 14th, 2008
这些都不是SOA
在和同事们讨论我们的服务化过程中,以及网上看到的一些帖子,甚至在某些SOA的宣讲会中,把以下情况都认为是在搞SOA:
- 使用web服务的应用就是SOA
- 使用RESTful的应用就是SOA
- 使用了分布式计算就是SOA
- 使用WS-*扩展的web服务应用就是SOA
- 使用了ESB产品,就是SOA
- 使用了SCA产品,就是SOA
- 使用了IBM,Microsoft等公司提供的SOA产品,开发出来的应用就是SOA
以上这些情况都不是SOA。SOA是以业务入口点,来自于实际的业务需求,以下例子才是真实的SOA。
XX航空集团开发的独立系统很多,现在需要把信息流整合起来,制作更全面的报表、提升信息流转的速度、方便信息分享、提高信息检索速度等,此时从业务信息整合的角度出发,以服务的思想构件了一个新的统一信息平台。
我们公司存在同样一个业务逻辑,会用在WEB平台,手机平台,管理平台,开放平台(还有其它原因,参考SOA,想说爱你不容易),原有的做法是共享类库,直接操作SQL等实现,现在利用SOA的思想,把这个业务逻辑封装为服务,供所有平台使用。
Yahoo中国和口碑合并,内部系统必然涉及到人员,业务流程的变化,采用SOA就能够化解之(我们常常看到一些报道,某公司收购另外一个公司,信息化系统的整合往往花费几年时间[当然还有其它原因,例如文化],甚至会失败。案例表明:采用SOA的公司,成功率高于不采用SOA的公司)。
参考资料:
http://www.infoq.com/cn/news/2007/07/soa-ws-relation
IBM提供的实践文章
IBM 内的 SOA 应用,第 1 部分: SOA 案例研究
IBM 内的 SOA 应用,第 2 部分: SOA 案例研究
IBM 内的 SOA 应用,第 3 部分: SOA 案例研究
IBM定义的SOA入口点:

星期四, 06月 12th, 2008
ESB产品升级准备:SOA、ESB、JBI、SCA、OSGI概念再学习、再理解
这几日看了许多SOA,ESB,JBI,SCA,OSGI相关的书籍、BLOG、文章、JavaOne上的一些资料,希望在ESB产品升级之前,能对这些概念再次进行学习、理解。明确术语,确定关系。
SOA
SOA是一种业务建模思想,是一种架构风格;它以服务为核心,构建系统;通过进化控制节奏;【摘录】支持对业务进行整合,使其成为一种能够相互联系、可重用的业务任务或者服务。
【注:此处的架构仅指技术相关的架构。】
- 一种业务建模思想
SOA是一种业务建模思想,而不是一种技术体系。它来自业务敏捷的需求,植根于业务,致力于提升业务的敏捷性。
最低层面:使用SOA的思想分析、重构业务,用服务的概念定义业务单元。实现层甚至使用现有技术体系,选择几种结构型模式:Façade模式,Proxy模式,Composite模式配合,从而达到原始的SOA层面。SOA并不强制我们必须分布,必须采用一些支持SOA的技术或产品,只要业务敏捷了,且当前技术架构也能够满足生产发展的需要,就是合适的。
- 一种架构风格
SOA也是一种架构模式,特别是一种分布式架构模式。
实践观点:第二个层面以第一个层面为基础,没有第二个层面,只有第一个层面,我们还可以说这个系统是SOA化的;没有第一个层面,只有第二个层面,这个系统是否SOA化,值得商议。(IBM提出的SOA切入点中,包含有以技术为中心的切入点【连通性】,从我们实践、公开案例的实践、专家有关SOA实践的书籍来看,以业务为切入点是最合适的,也是最容易成功的,获得组织支持的概率也大;单一的基于技术切入SOA架构,案例较少)
它的一些特征:
以服务为基本单元,可以把服务视为构件。
服务质量可度量,且可以提升。
基于开放标准。
该架构同时是一种分层架构。
具有分布的能力。
与技术无关性。
鼓励扩展。
支撑业务敏捷的要求。
架构层面主张组合。
- 服务设计的原则
松散耦合
服务契约
自治
抽象
复用性
组合性
无状态性
可发现性
互操作性
ESB
ESB是一类中间件产品的通称;是一种分布式的技术架构,以中介为核心概念;是一种支持SOA实施的技术选择;来源于集成的需要,实现服务、系统之间的互联、整合;ESB产品通常提供一种容器,方便插入各类通用服务(编排服务、消息服务等)、提供服务虚拟化的能力(协议和模式、接口、身份等)、提供面向方向的连接(安全性、管理、日志记录和审核等);支持业务逻辑和实现的技术逻辑的分离。
最常用到的特性:
-
它使用XML(可扩展标识语言)作为标准通信语言。
它支持Web服务标准。
它支持消息传递(同步、异步、点对点、发布-订阅)
它包含对服务编制(orchestration)和编排(choreography)的支持。
它包含智能、基于内容的路由服务(itenerary路由)。
它包含转换服务(通常是使用XSLT),在发送应用和接收应用之间转换格式,简化数据格式和值的转换。
它可以条件路由,或基于非集中策略的消息转换,即不需要集中规则引擎。
它提供对服务监控、治理相关的内容。
-
参考资料:
http://www.ibm.com/developerworks/cn/architecture/ar-esbpat2/index.html
http://www.ibm.com/developerworks/cn/architecture/ar-esbpat1/index.html
http://www-128.ibm.com/developerworks/cn/webservices/ws-esbscen/index.html
http://www.infoq.com/cn/articles/ESB-Roundup-Part1-Defining-ESB
http://www.ddj.com/java/201200303;jsessionid=DP5D5J5VEP4XKQSNDLPSKHSCJUNN2JVN?_requestid=459785
JBI
【摘录】是基于面向服务体系提倡的方法和原则,为了解决 EAI 和 B2B 若干问题的 Java 标准。JBI 定义了基于插件方式的架构,以便服务能融入“ JBI 运行时”环境。 JBI 提供了详细的接口,使服务能与“ JBI 运行时”环境交互。
- 资料:
http://soaneu.blog.com.cn/index.shtml
http://www.jcp.org/en/jsr/detail?id=208
http://www.infoq.com/jbi
服务引擎、组件绑定图:

本图强调了服务引擎,组件的绑定方式,更倾向与产品的扩展。对业务级别的服务模型支撑比较弱,业务通过API来实现与JBI产品的交互。
SCA
服务组件体系结构 (SCA) 是一个规范;是一种架构模式;是一种通用的面向业务服务的组件模型;定义了部署模型;提供了实现提供服务和使用其他服务的组件、组装组件,以通过服务引用其他服务的方式来构建业务应用程序–与SOA组合的原则一致;SCA是平台无关的;SCA是一种编程模型;支持业务逻辑和实现的技术逻辑的分离;是一种支持SOA实施的技术选择;SCA支持组件的分布。
【摘录】is a set of specifications which describe a model for building applications and systems using a Service Oriented Architecture. SCA models solutions as sets of service components offering services and making references to services supplied by others, which are combined together by composites which wire references to services and which declaratively apply bindings for communication methods and also apply policies for aspects such as security and transactions. SCA extends and complements prior approaches to implementing services, and SCA builds on open standards such as Web services.
- 资料:
http://dev.yesky.com/topic/308/7667308.shtml
http://www-128.ibm.com/developerworks/cn/webservices/ws-theme/ws-soa.html#sca
http://www.davidchappell.com/articles/Introducing_SCA.pdf
http://www.osoa.org/display/Main/Service+Component+Architecture+Home
http://www.infoq.com/sca
http://www.infoq.com/articles/setting-out-for-sca
http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-41500&yr=2007&track=3
核心概念图:

本图强调了组件模型,服务组件之间的组合模式,把业务级别和系统级别的组件,同等对待。提供了业务组件接入容器的方式。完全符合SOA的概念。
OSGI
【摘录】一个开放并且提供统一接口标准的体系框架,基于这个体系框架,服务提供商,程序开发人员,软件提供商,服务网管运营商,设备提供商能够协调地联合起来开发,部署以及管理向用户提供的各种服务。
【摘录】provides a service-oriented, component-based environment for developers, primarily on the
Java platform. It provides a dependency resolution mechanism, with version support and also offers standardized ways to manage the software lifecycle. OSGi is a particular boon when using different components that use different versions of some shared package. These capabilities greatly increase the value of a wide range of computers and devices that use the Java™ platform.
- 资料:
http://www.riawork.org/
http://www.infoq.com/osgi
http://www.osoa.org/download/attachments/250/Power_Combination_SCA_Spring_OSGi.pdf?version=3
http://xml.coverpages.org/OSGi-ServicePlatformOverview2004.pdf
http://www.blogjava.net/BlueDavy/archive/2007/10/14/152820.html
http://www.blogjava.net/hx9111/archive/2006/11/10/OSGi-SCA.html
http://www.blogjava.net/zhaobin/archive/2007/11/06/158485.html
相互之间的关系
- SOA – ESB
ESB是一种支持SOA实施的技术选择。
- SOA – JBI
JBI是Java领域一种支持SOA实施的技术选择。
- SOA – SCA
SCA是一种支持SOA实施的技术选择。
- SOA – OSGI
没有直接关系,目的不一致。
- ESB—JBI
JBI和ESB是互补的。JBI提供一个模型和将集成组件作为服务的标准接口。JBI可以宿主在一个应用程序服务器环境或者在一个ESB容器中。ESB提供了一套基础架构包括了事件驱动的SOA,高度分布的路由目的地命名,企业消息能力和分布管理能力。
- JBI – SCA
【摘录】SCA has a strong model for defining composite applications、Services can be implemented in multiple languages、Can bind interfaces and references to different technologies。
JBI:Defines a standard, loosely coupled, ESB architecture、SE / BC are exchangeable between JBI implementations、Provides standard abstraction for all JBI components。
融合性:When combining JBI and SCA, all JBI service engines can be used in SCA components, SCA components can be called from JBI, SCA applications can be deployed as service units in a JBI container.
- SCA-OSGI
相同点:都是一种规范;都是一种架构;一种编程模式;都定义了模块,服务概念。
不同点:OSGI强调模块的动态性;SCA强调服务的分布性;OSGI来源与单个JVM产品架构的需求;SCA来业务SOA化的技术需求;OSGI更适合产品架构;SCA更适合业务系统架构。
融合性:SCA可以作为Bundle部署到OSGI环境,以增强OSGI环境的业务架构解决能力;OSGI可以作为一个模块部署到SCA环境中,从而利用OSGI环境下的基础通用服务。
- SCA-ESB
相同点:都是SOA的一个可选的技术方案;都基于服务的概念;都是可分布的;都提供插件特性等。
不同点:SCA是一个标准,ESB是一个概念;SCA有模块的概念,ESB没有这个概念;SCA是一个组装车间,ESB是一个中介机构;SCA简单而清晰,ESB复杂而模糊,不同产品特性千差万别。
星期五, 06月 6th, 2008
闲话SOA服务化之–接口和协议
在系统SOA化之后,不可避免的就遇到接口的问题,在Java环境使用XFire。常遇到:接口不匹配,服务依赖者不能动态切合等问题。
后来不知如何,就说起了银行的系统:多平台,多语言,物理分布,有购买的产品,有多开发商开发的产品,业务负责,存在协议(多是核心金融业务)、接口调用等多种方式。很是佩服之。随就接口方式和协议方式进行了一些比较。
【术语:
- 协议 — 协议包含了数据格式,同时规定了行为等方面的内容,例如邮件协议,RPC协议。
- 格式 — 对信息的编码。例如:XML格式。
- 接口方式 — 指程序接口调用实现业务交换的方式。例如:java API调用。
- 协议方式 — 通过某种报文(信息是满足格式的)实现业务交换的方式。例如:收邮件,发邮件。
】
比较点
基于接口
基于协议
开发人员编程期的易用性
容易理解
使用方便
可以直接编程
较难理解
使用较麻烦
不能直接编程
架构从单系统到多系统变迁的过程
平滑迁移
修改协议相关的代码
支持工具的方便、稳定性
有现成的工具,如xfire
稳定性很好
不需要考虑序列化问题
与Spring整合的非常好,程序员不需要关注序列化,传输,安全等问题
外界维护工具
可以使用xml binding1等工具1
需要考虑序列化问题
缺少一个类似这样的完整工具,让程序员爽
需要自己维护工具
自我校验
基于接口校验,例如
验证
工具自动支持
很容易自动方式检测不匹配性
编译时检查
基于协议校验,例如
schema验证
缺少工具自动支持
运行时检查
方法名称变更
需要变更,甚至重新发布系统(可以通过配置文件来避免重新发布)
不需要变化
通常协议内部包含着业务指令号;
rpc方式的方法名,类似指令的作用
方法参数变化(增加,减少)
需要变更,重新发布系统
没有方法参数概念
方法参数类型变化(具体值得内涵没有变化,例如
123,从int变为string)
可能会失败
没有方法参数概念
参数是对象类型,对象属性变化(增加,减少)
增加不会失败,是否变化,依赖业务需求。如果业务上兼容该协议,那么也不需要变化;否则需要重新发布系统
这也是风险点(但可评估)
减少没有测试
没有对象参数概念
协议变化(增加,减少协议项)
(与)
没有协议概念
可能会失败,依赖业务需求。
如果是技术上的一个协议项变化,那么可以不变化,也不会失败
如果业务上兼容该协议,那么也不需要变化;否则需要重新发布系统
这也是风险点(但可评估)
增加方法
可能在自检查的时候系统级别失败
业务级别会失败
相当于增加了一个业务指令
系统级别不会失败
业务级别会失败
存在同名方法(参数类型不同,但相似)如(
int和double
会失败
没有该概念
工作流类、
JS类产品与业务结合的时候
需要引入多个接口
或使用动态
API模式
直接操作协议
一个业务的多个操作时的表示,例如:增,删,修改,查
通常是多个方法来表示不同业务
一个协议
+指令就可以解决
缺点:需要细心,别用错了指令(测试阶段可以解决)
运行期稳定性问题
测试和系统检查可以确保运行起稳定性
需要很细心的测试和部分系统检查来确保运行期稳定性
接口变动太随意
由于容易,且是基于操作的,所以每个程序员都可以自由使用
由于复杂,而且是基于业务的,需要清晰、仔细的定义,反而因祸得福
管理方面
SOA的相关支持工具,比如服务仓库,能够使用一种元语言完整地定义服务的契约,再根据这些元定义生成
一系列东西
缺少这方面的支持
需要自己开发相关工具
但产品经理可以通过业务层的管理来管理协议,从而约束开发
版本问题
解决较为麻烦
解决较为容易
与路由概念配合
较为麻烦
由于基于协议,与路由结合起来反而容易
投入成本
低
高
学习成本
低
较高
从实施工程的角度看
组织的软件成熟能力度要求低,项目管理要求中.开发人员人员水平偏低,更需要强约束的框架或者实现方式。
组织的软件成熟能力度高,项目管理要求中高
【说明:】虽然SOAP也定义了文档格式,但在实际使用中,使用者很少。毕竟,文档格式方式的WS走到是协议思路。
【闲话杂聊】
最近看到REST方式,它非常流行,很多网站的OpenAPI都基于它来搞,我们也准备尝试之。看了深入浅出REST一文,初步了解了一下它的资源概念,还是有些不知所措;又看到Building Web Services the REST Way一文,其中一句话“REST - An Architectural Style, Not a Standard”,指出了本质,原来我们可以在它的框架下使用接口方式,也可以使用协议方式。
结合它的目标是描述资源—互联网资源,我们就会发现,互联网界的大部分内容都是用协议来描述的,例如:HTTP协议,HTML协议等。 再看看google的RESTful API Specification,虽然是API,也基本是用半个协议的方式进行描述(它的JS标准部分,完全是接口的方式,毕竟这个时候不存在整合的需求。Facebook的API,也基本上接口方式,输入参数按照HTTP提交方式,输出部分到部分定义了格式。)
在开放互联网界使用的Rest + 格式方式 ==?协议吗【注:我看到axis在搞 Rest (序列化部分用XML格式),这东西和非Rest 的WS有哪些本质区别?】在企业内部是否依然也有很强的生命力?— 留给实践来检验吧。
【后感】
接口:内存调用 –〉RPC调用 –〉IDL系列(COM+,corba,RMI等)-〉SOAP系列 ,这一条发展线路基本是程序员主导。从抽象的角度看,程序员是不关心业务的,因此尽可能的让集成方法远离业务层,从系统层面解决之。
协议:EDI,ebXML系列,信用卡数据交换协议,国人搞得cebXML等等,这条线路基本是业务专家主导。从抽象的角度看,业务专家不关心系统如何实现,它更关注业务的标准化。
接口和协议看似两个简单的概念,但它们代表了两种系统整合思想,两种架构思路。他们有时候是对立的,有时候又是糅合的,很有些哲学的味道,对立统一规律(辩证法)。
星期二, 06月 3rd, 2008
服务化的行军中:Enum使用,快乐的痛苦
JDK1.5之前,一直使用类似apache commons lang中提供的Enum。
由于如下几个原因,换选了java Enum。
- 远程服务在序列化旧式的Enum时,默认是不支持的,需要单独进行定制。常用的WS,Hessian,XML绑定工具,都不能很平滑的支持,且时不时有些莫名其妙的故障。
- 在高并发的时候,存在性能瓶颈。这也是业务量上去之后,才发现的。
- 这个旧式的枚举在对象序列化的时候,有些偏大(同样的常量字段:350字节左右,java Enum 大概124字节左右–其实也不小呀),和其承担的角色不像匹配。
- JDK1.5提供的枚举,简洁,方便,序列化工具基本都支持。
新老枚举使用在了如下场景:
- 业务常量
- 错误代码
其实使用的场景还是很简单的,开始我们使用的很开心,很舒服,到后来,却有些苦涩了。
- 在我们SOA化的进程中,核心业务单元都独立起来了,核心业务采用服务-组件模式(聚合模式),产品层调用服务层,完成一次业务行为。在这个过程中,每个组件单元都有独立的业务逻辑,相互不干扰,因此就产生了不同的业务常量Enum,和错误代码Enum。后来发现,部分业务常量Enum的部分语义有差异,导致一个业务逻辑段内出现2种业务定义;最头痛的是错误代码,无法直接给产品层返回,如果返回字符串,在反转的时候,存在不清楚枚举类型的问题。
- 有些业务单元吸取了前次的教训,把所有的错误代码定义在了一个枚举中,用起来好似不错。唯一不爽的是:wsdl文件,居然把所有的枚举都给列出来。
- 在服务化不断进展中,出现了一个核心业务调用其它几个核心业务,这最外面的服务痛苦不堪,它的处境与情况1相似。
- 由于某个偶然的原因,还出现了A程序用b1,b2,b3枚举来详细区分业务,B程序用b来区分业务,产生了b={b1,b2,b3}的业务语境,由此出现了二维枚举定义法。
- 老的枚举实在太多了,只好保留,产品层采用枚举转化化。最头痛的是:核心业务重新梳理之后,增加了许多常量和错误代码,产生了不一致的情况。
在使用过程中,WEB层又提出了一些特殊要求:下拉框,复选框,都需要提供复杂的枚举,例如{name,value,msg,sequence},实际使用的复杂度,超出了原始的常量要求。这些枚举就在我们的SOA环境中生存了下来,Happy的传来传去,有些随意的在多个系统之间溜达。
一直梦想JDK的Enum类能够提供如下方法,最后,只好自己搞一个了:
public static <T extends Enum<T>> T getEnumByName(Class<T> cls, String name);
public static <T extends Enum<T>> T getEnumByValue(Class<T> cls, String value);
public static <T extends Enum<T>> List<T> getEnumList(Class<T> clazz);
public static <T extends Enum<T>> List<String> getEnumNameList(Class<T> clazz);
public static <T extends Enum<T>> Map<String, T> getEnumMapKeyIsName(Class<T> clazz);
这个过程中有好些不合理的地方,仍需解决:
- 大规模SOA化业务过程中,业务常量的定义,使用Enum,是否是一个好的选择。好处:程序员比较容易找到;常量比较清晰,不容易出错;管理起来方便;变化周期较长,系统也允许重新发布;对分析、设计人员的要求相对较低,程序员可以方便的增加,变更业务常量。痛处:上面提到了一些,特别是最外围的聚合业务,有些不爽,产品层最是不爽。
- Enum作为服务接口参数,在跨越系统边界的时候,变相增加了系统的耦合度。
- Enum在域对象中适用,该域对象作为服务接口参数传递,在某些序列化方式下,会出现错误。特别是xfire的序列化,支持的很不好,如果域对象中还用Map<Enum,T>之类的,也会出现错误。此外,在open的服务接口中,可能出现其它语言不支持Enum概念的情况,因此在服务接口处,尽可能用原子类型;不爽的是,枚举的某些限制作用就会丧失,在程序内部可能出现大量比较、反转的情况。
- 错误代码,定义为枚举,不爽,但好处和第一条一样。比较HTTP协议,信用卡标准等,可见我们在业务协议标准化层面还有得发展,如果内部业务之间的协议标准化了,那么我们的SOA,可以进行的更好,我们的产品经理,甚至可以通过这些常量,代码,协议的维护,实现对产品的可控性。
- 二维枚举要避免。这其实也是业务没有能够标准化,一不小心就产生的变异。特别是第一个版本的业务设计,对后续的影响很是深远,从另一个层面表现出来的是:数据完整性发生了变化。可喜的是,说明了业务发展飞快;可忧的是,业务架构越来越要求具有前瞻性,扩展性,否则大家都很痛苦。
- 业务常量,大都具有很强的业务语义。定义的准确性,合理性,对后期的维护有很大的影响。跨业务功能单元的局部重叠的业务常量,表现起来(用Enum定义)痛苦,使用起来也痛苦。如何使好呀?
- 新老枚举共存为后续的痛苦,埋下了伏笔。
- 一旦服务开放了,又可能存在一层映射。
- 不用Enum,尝试某几个常量不用Enum,开始用起来很爽,测试维护的时候,傻了,这个常量是1,2,3;大于10个地方用到了,后来发现一个BUG,不能确定常量的业务语义了。特别是其它人阅读代码的时候,一头雾水。只好重新用Enum来定义,无论理解,维护都方便了。
- 规范化枚举的格式,开始定义枚举,有多种方式,直接定义:EnumName、带转义值定义:EnumName(value)、带文本说明的定义:EnumName(value,message)。各自都很不相同,后来有做管理平台的哥们用的时候,发现很不爽,想写个Utils都不行,还不能满足要求。最后同意格式:EnumName(value,message,扩展值),EnumName表征业务,value是实际数据值(如果本身就和EnumName相等,那么也要写之),message是说明文字,枚举构造器后面的参数业务自己定义。这里面,最怪异的是message,为了方面,直接用中文了,而没有用resourceBundle之类的技术,留待以后解决之。
星期一, 06月 2nd, 2008
SOA,想说爱你不容易
今日看到eBay的一篇架构实践文章,想起了最近1年,我们公司向SOA迈进的一些方面。
驱动我们公司进行SOA的原因思来有如下一些方面:
- 代码增长太快,系统地扩展性太差;开发过程中,往往由于一个小的变动,就会重新发布整个系统
- 系统庞大,功能错综交叉,还在不断的堆积新功能,耦合度递增
- 业务部门对敏捷性的要求,市场是变化的(市场变化的速度加快了,竞争对手创新的速度也加快了),产品也需要能够适应变化
- 业务需求增长太快(市场变大了),同时进行的并发项目太多,非但进度缓慢,而且代码合并,集成测试都带来很大挑战;而且许多需求被压制,引起业务部门的不满意
- 一个系统容易掩盖业务的本质,使我们不能很好的分离业务逻辑和产品(一个业务逻辑,可以使用多种包装方式形成不同的产品,例如:登录业务,可以由weeb登录产品,wap登录产品,终端登录产品,接口登录产品等。)
- 把一些本来属于产品特有的逻辑也混杂在业务逻辑中,使得业务本质模糊,代码丑陋等等
- 每次启动工程都需要2-5分钟,所有人都已经不能忍受
- 系统发布计划越来越复杂,发布频率越来越高,稳定性变得越来越不可控
- 组织结构频繁变动
- 业务核心随着战略的变化,逐步演变;系统由单一核心业务向多个核心业务为中心的模式展开
- 随着销售的引入,产品化的需求变得很强烈
- 管理制度发生了变化,条例(安全相关、行业法规相关,法律相关)更加严格,细化
- 计划引入项目成本考核,目前状态下的成本明显偏高,架构必须为成本的降低做出贡献,提高资源生产率
- 业务监控,管理的需求提上了日程
- 各种规则、架构约束力的作用日渐消弱,系统逐步向混乱的方向演变。
- 业务系统和管理系统存在两套代码的现象,增加了业务逻辑不一致的几率,代码维护成本(例如Fix业务BUG)随着业务的复杂递增,测试成本也随着递增
- 开放平台战略的确立,要求业务必须标准化,服务化
- 等等
当然了,我们架构组自身也实在无法忍受。
采取如下策略,历时一年,逐步SOA化(社会主义初级阶段)。
1、首先进行业务的服务化,把我们的系统划分为几个核心业务块,然后挑选其中的一块业务(例如:会员相关业务)进行服务化,逐步把几大业务搞定。
2、第一块业务服务化的同时,研究相关的基础技术。例如:ESB、分布式事务、OSGI框架、开发模式、系统部署模式、业务用例如何向系统用例转化、业务粒度的设计原则等。同时研究对立部署业务单元对性能、可靠性、稳定性方面的影响。
3、随后服务化的时候,引入可靠异步模式,包括业务流程异步化。
上面的过程和eBay架构实践中介绍的几点有一些相似性。
Scalability Best Practices: Lessons from eBay一文
- Best Practice #1: Partition by Function
- Best Practice #4: Decouple Functions Asynchronously
- Best Practice #5: Move Processing To Asynchronous Flows
在我们进行SOA的过程中,我们初步实现了按照大的业务快进行切分,还未能够实现对更细的功能点进行梳理。一方面是为了避免风险,另一方面我们也未能从业务上搞清楚再细粒度的功能点如何划分。
4,5两个技巧提到异步,在这二点上我们进行了一些有益的尝试,但还是未能破除目前太多的同步调用现象。究其原因,我们未能从业务上定义清楚更细粒度的功能点,以及它们之间是否适合异步。
从目前实践效果来看,我们解决了当时驱动我们SOA化的一些方面,同时引入了如下困难:
- 测试的困难,每次项目分支,由于其依赖其它业务核心,导致需要同时切出多个分支,申请多套环境
- 开放的困难,很多程序员不能理解这次调用到底访问的是谁?
- 版本问题
- 服务的监控和管理
- 最头痛的是:业务服务思想的延续性,已经出现部分业务核心偏离了当时的业务分类原则
- 产品层存在粒度过细的信息查询,没有考虑到SOA场景下,产品层信息使用的策略
- 技术体系相对复杂化了,开发、测试需要重新学习这种架构
- 等等
关于业务异步化:从长远来看,业务异步化的研究,会给我们的产品化、开放化、SOA化、网格化计算提供有力的支撑,同时显著提升我们系统的扩展能力。但从另一个方面来讲,它给我们的程序员,业务分析人员带来的困惑也会更多。
SOA是可持续的战略,不是一次项目
常常听到如下关于SOA的说法:
- 我们完成了SOA化改造。
- 我们的SOA化,已近实现了80%。
- 这次项目是为了实现SOA化,因此要请有这方面经验的公司来实施。
- 从技术角度层面来说,我们达到了SOA化的目标。
- 这是我们最后一个SOA个项目
- 等等
如果这些话出自程序员,项目经理等人员,也是无所谓的;如果出自IT管理层的人员,哪就是一种可怕的想法了。因为他把SOA仅仅看作是一次项目了,而没有把它作为战略。这样的后果也是可以预见的,最终本次投资将会失败。
因此,建议那些准备实施SOA的公司,首先回答这个问题:SOA是贵公司的一个战略吗?
为什么要回答这个问题?
- 从SOA概念来看
- 从SOA目标来看
- 从IT管理角度来看
- 从系统分析角度来看
- 从技术特征来看
关于什么是SOA,我有几篇文章,可以参考(《这些都不是SOA》,《ESB产品升级准备:SOA、ESB、JBI、SCA、OSGI概念再学习、再理解》,《SOA,想说爱你不容易》)。丛概念上可以看出,SOA不少技术问题,它是一种思想,一种架构,因而不可能通过一个项目就把这种思想或架构完全实现;思想也是会发展得,今天的思想在明天或许就会不适应。
SOA的目标是解决业务敏捷性问题。如今,大环境复杂多变,任何一个公司都不敢说自己的业务就是这几个、自己的业务会一直不会变,很多企业,在很短的周期内,就会推出各类产品(特别是服务类企业,例如:银行、互联网企业等)。只有那些能够快速适应变化,主动寻求变化的企业才能够生存下来,发展起来,例如:会跳舞的大象IBM,IT行业最大的特色就是变化快、发展快,如果IBM的业务不能敏捷的适应这种变化,它还能跳舞吗?正因为IBM深刻理解了SOA的目标,因而它把SOA看作一种战略–可持续的战略。
对于IT主管,一定要确保本公司的IT战略是可持续的,不能今天一种想法,明天又看到什么好思想,就换了一种想法,或者换个主管,就彻底换了战略(这种做法,就像我们国内的城市建设,路总是修不好)。既然从一种思路切合到了SOA领域,那么再次切换的成本将会更高,也不可能多种思路同时进行(吃得多,嚼不烂)。此外,谁能保证一次项目就确保几年内业务变化的需要?从我们实施的经验来看,必须持续的进行SOA化,才能确保SOA持续的发挥效果。
每次项目都要进行系统分析,都是基于当前的业务进行,那么不可避免的就会有一些盲点(从认知的角度看,人不可能一次就抓住事物的本质,何况大多数系统分析员不具有这种能力)和不合理支出。这些问题,只有在实施后一段时间才能发现(我们自己的实践经验);此外随着补丁的实施,原有的系统已经恶化,和最初的SOA化目标越来越远。此时,如果不能再次用SOA的思想重新审视系统,就将彻底失去了SOA带来的好处。
SOA非但不能让系统架构变得简单,反而变得复杂了(系统设计要求变高了、系统部署复杂了、发布复杂了、各类SOA相关技术的引入增加了对人员的要求),这也是为什么要引入SOA治理。从这一点来看,只有持续的SOA化,才能最终发挥SOA技术架构的好处。
再次提醒将要进行SOA化的朋友和已经进行了SOA化的朋友,把SOA当作贵公司的可持续的战略来看,而不要认为它紧紧是一次项目。
SOA实践之:Java服务接口设计的一些实践准则
在SOA领域,一些OO领域的接口设计原则具有很好的借鉴意义,但随着SOA化带来的分布式特性,有些东西就需要进行特殊处理。下面就我们进行SOA化过程中接口设计过程中,曾经比较容易出现过问题的地方进行部分总结。
【术语说明】
-
服务与业务组件的定义:
- 业务组件:最小的业务逻辑单元,例如:密码验证组件、登录组件。
- 服务:业务模块提供给外部的核心业务逻辑,服务组合业务组件。例如:修改密码服务,会使用密码组件的验证服务,也会使用登录组件的修改密码服务。
【说明:】可否密码验证组件的功能合并到登录组件哪?可以的,此处之所以单独分离,与我们提供多种密码验证机制有关,登录组件对应的业务并未完全涵盖密码验证组件的功能。
- 服务接口的方法,禁止重名(overload特性)。大多数序列化工具【例如:XFire】对重名方法进行处理时,都不可能避免的存在或多或少的问题。为了减少麻烦,还是放弃OO的这一特性,或者在面向服务领域,重载本身就不是一个特性。
- 服务接口的方法,避免返回异常【我们是禁止异常,包括业务异常、系统异常】。这个要求看起来违反了一些对象设计的原则,从实际使用角度来看,具有如下好处:很多工具对异常序列化很容易出现错误;一不小心,外部使用者还会产生异常依赖;需要外部使用者自己把异常翻译为业务语义【从业务角度来说不是件好事情】。
- 服务接口必须有清晰的文档说明,对于常量性质的参数,要列出支持的常量值。
- 服务接口尽可能把查询和业务方法分离【非必须】。好处是使用AOP时简单方便,对于查询方法进行特殊处理时也比较方便,例如:与cache整合、与搜索引擎整合、与特殊权限要求进行整合(例如,对返回信息按照权限进行过滤)等。
- 服务接口参数排列按照如下原则:操作主体对象或ID,业务参数{…},环境参数。
例如:verifyPassword(String operatorId, String password, ServiceContext serviceContext)
operatorId是操作主体的ID。
Password是密码。
serviceContext是环境参数。 - 业务处理类接口,返回值可以采用统一对象模式。例如:ServiceResult:
public class ServiceResult<T> implements Serializable {
private static final long serialVersionUID = 760567785564620157L;
private boolean isSuccess;
private String resultCode;
private T resultObject;
public boolean isSuccess() {
return isSuccess;
}public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}public String getResultCode() {
return resultCode;
}public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}public T getResultObject() {
return resultObject;
}public void setResultObject(T resultObject) {
this.resultObject = resultObject;
}
}
采用这种模式,实际是按照协议的角度进行设计,所有服务按照统一的包装模式返回。 - 服务接口的参数避免使用Object类型,集合类型要指定具体对象类型。原因:当使用Object时,使用者获取到WSDL文件时,不知道该传递什么业务数据,如果是其它语言的调用者,更无法理解了;这类接口设计违反了业务SOA的原则,暗含着如下潜台词:业务上不明确的,不清晰的。
- 服务接口避免使用集合类型,尽可能使用数组类型。
- 服务接口中使用枚举的原则:如果是对外界发布,避免使用枚举;如果使用者众多,避免使用枚举;如果是内部几个专用系统使用,可以考虑使用枚举,可以参考《枚举产生的系统耦合性》。【文档的清晰化,可以化解常量参数不明确的问题】
- 服务接口避免设计成面向数据的操作,例如:updateStatus。这类接口,通常包含太多的业务含义,甚至没有业务含义,需要外部使用者去理解业务内部的细节,否则无法进行操作。这也是我们设计服务接口时,需要特别注意的地方,不要让外部使用理解业务内部是如何存储的,结构是什么样的,这样会导致业务耦合度过高,服务内部发生重构,变化时,外部使用也需要进行变化。
- 服务接口层建议设计一个统一的模板框架,来处理性能分析、特殊参数处理(例如:ServiceContext)、事务处理、异常处理、日志处理、事件处理、审计处理等具有共性的行为。
- 服务接口的方法名避免以:is,get开头,用find,check等来代替之,避免Java序列化工具把该类当作Java Bean进行处理。
- 业务组件中异常的要求:所有的业务组件,如果发现违法业务原则的地方,需要中断程序的执行,那么throw统一业务异常,该业务异常可以借鉴如下方式设计:
public class ComponentException extends Exception {private static final long serialVersionUID = -6900280471536579015L;
private ErrorCodeEnum code = null;
public ComponentException ErrorCodeEnum code) {
super();
this.code = code;
}public ComponentException ErrorCodeEnum code, Throwable e) {
super(e);
this.code = code;
}public ErrorCodeEnum getCode() {
return code;
}public void setCode(ErrorCodeEnum code) {
this.code = code;
}
}坏处:从异常名看不出明确的业务语义。
好处:避免服务层需要捕获多种异常;业务语义通过ErrorCodeEnum返回到业务层。 - 业务组件内部尽可能少的进行事务处理【除非有特殊的需求】、异常处理【除外业务组件自身组合了外部的业务服务,此时需要处理异常】。
好处:统一由服务层进行处理,可以避免事务处理的错误。不进行异常处理,可以避免异常转义时,出现信息丢失;此外,如果使用了统一异常,那么就更不能在业务组件内部进行异常处理了,否则会发生原始业务限制规则被丢失的可能。
对于一些基本原则,可以参考《SOA实践之:在程序层,面向服务的设计准则探讨》一文。
使用方,推荐使用代理模式来使用外部服务。
1、可以进行一些特殊处理,例如:网络异常处理,远程性能评估等
2、对内部提供重业务层面的方法,屏蔽环境参数
3、外部服务接口发生变化时,或许修改一处就能够满足变化
4、如果要对传输层、安全进行定制时,会非常方便
【参考资料】
模块分解原理的探索
Interface Design — Best Practices in Object-Oriented API Design in Java
Part 1: Exploring the development, interfaces, and operation semantics of services
Part 2: Exploring the development, interfaces, and operation semantics of services
SOA架构之性能解决策略之一【引入Cache过程的思考点】
采用SOA架构实现了业务的分离、重用、对BPM的支持。经过初步的测试,这种架构不能满足性能的要求【前提:SQL已经优化,数据库cache已经不能满足需求】,就当前的应用环境来看,引入cache是解决性能的一个办法,这也是比较通用的一个方案。
目前网上已经有大量的cache实现,介绍cache原理,cache使用案例的资料。下面就我在使用过程中的一些思考点分享一下。
1. 在SOA系统架构的那一层进行cache

系统架构如图所示:可以在1、2、3、4、5每个点考虑增加cache。
在1这个位置采用cache,通常采用Apache相关的cache扩展。
在2、3、4这些位置采用cache,可以使用本地cache,或者远程cache。例如:ehcache、Memcached等。
在5这个位置,可以通过增加服务器内存,调整数据库cache;或者通过数据库伸缩性实现性能提升。可参考该文《大型网站的架构设计问题—-大型高并发高负载网站的系统架构 》【主要讲了MySpace的用户量不断增长过程中,如何逐步提高性能】或相关数据库的性能提升方案。
在2这个位置,可以缓存web页面,业务数据对象等。
在3这个位置,可以缓存业务数据对象、服务相关配置信息、路由规则、消息数据等。
在4这个位置,可以实现通用数据访问层,实现统一数据源查询,业务数据对象可以缓存起来,例如《ebay的架构中的DAL层》。【这一层同时能够为分库,多数据源系统,提供统一数据访问能力。】
具体在那一层实施cache以提高性能,需要依据自身系统的特点来实施。以内容为主的系统,考虑在1,2处采用cache;也业务为主的系统,考虑位置2、3、4、5处采用cache;采用SOA架构的业务,考虑位置3、4、5处采用cache【如果数据库存在切分,多源的情况,可适当倾向位置3,4】。我依据自己的需要,选择了如下一个方案。

2. 资源重复利用的频率【命中率】
之所以要采用cache,目的就是要提供资源重复利用率,减少数据库访问。因此先要评估使用cache能否达到目的【例如:提供性能】,如果命中率太低,需要考虑别的方案;如果批量查询很多,命中率又很低,可考虑放弃部分即时性,用搜索引擎等方案。
3. Cache产品选型
在Java平台,对于内存cache,可以选择Map系列,Ehcache,OsCache等;远程cache,分为中央模式,例如Memcached等;Cluster模式,例如:JBoss Cache等。具体使用那个cache,要依据:缓存什么,性能要求,数据量,可伸缩性(例如1个月之后,就需要加服务器了),事务要求,过期特性,一致性要求等来选择。
我的这个案例:性能要求高;能缓存60%的情况下命中率已经很高;数据量很大,但增长慢;随时需要增加服务器,以增加缓存的数据;不需要考虑事务,业务处理时,直接使用数据库锁,也即允许部分查询脏数据;按照数据特点,分别采用不同的过期时间;一致性要求高。因此选择了Memcached。
【资料:】
了解cache基本知识,java cache产品的一些特性,可以参考《Cache Insight》
一篇关于cache选择的文章《Cache的选择以及特性建议》
一篇关于远程cache的文章《Remote Cache, Transaction》
一篇关于分页情况下,cache使用策略《分页 & QueryKey & 预取》
我选择了Memcached作为远程cahce,推荐大家去官方网站看看。
4. 资源如何在cache中存储、资源粒度的选择
在cache存储的资源粒度,首先依据cache资源的特点,例如登录者基本信息,就完全可以一次性缓存起来,对于聚合关系结构的业务对象,在缓存的时候需要考虑业务特点,如果业务上对聚合对象内部的对象访问就很频繁,那么就考虑选择小对象力度缓存,否则考虑大粒度对象。第二点是cache自身的特点,本地JVM cache,可以考虑存储大对象,因为此时没有网络访问、数据流量的考虑,那么即使业务上小对象访问比较多,也可以考虑完全缓存整个对象关系;如果是远程cache,那么就要依据大粒度和小粒度对象访问的频率,然后决定。
【注】:查询返回的集合对象,不适合在cache中存放。
对象关系过于庞大时,也不适合完全存放在cache中。
-
资源序列化:在使用远程cache的时候,需要考虑对象序列化的问题。
- 如果是Java序列化,那么资源对象内部,不要包含非数据类对象,例如服务类,Logger等。
- 资源对象内部的数据属性如果使用了Long,Integer,Enum(包括自定义枚举)等非原子类型的对象,需要考虑序列化定制【如果资源量比较小,cache服务器资源足够多,可以延后考虑,但不能不考虑】。原因是对象序列化,会导致序列化后的二进制数据偏大,特别是Enum类型要引起关注【可参考《服务化的行军中:Enum使用,快乐的痛苦》一文】。
- Hessian,XML序列化同样存在上面存在的问题。
key的规划。坚持如下几个原则:尽可能用外部可以提供的属性作为key;作为Key的属性,尽量避免重复的业务上的重复,例如:多个业务用同一个业务语义作为Key;Key之间存在关系,但多个Key指向同一个业务对象,此时只选择其中一个与对象直接cache,其它key与这个Keycache;Key如果能够按照某种规则推算出来,切勿cache。
【注:】远程cache情况下,同一个对象中存在静态数据和动态数据时,当cache的时候,可以分别建立cache【特别是对于一个关系复杂的大对象,意义更大】。
5. 资源过期策略
缓存在cache中的对要要可以采用一定的过期策略,例如:某个对象缓存10分钟,因为它在10分钟之内还是能够被重复利用的;有些对象无限期缓存,因为它会被长期使用,此时对象是否被从cache中清除,由cache算法负责;最简单的方法是,不设置过期时间,由算法清楚,最终剩下的数据最有可能是重复率最高的。如果担心数据一致性的问题,那么可以依据业务对象特点,分配不同的过期时间。
6. 资源一致性解决方案
使用cache,最麻烦的是解决一致性问题,特别是对于业务系统,这种要求更高。
最简单的方式是:资源发生变化,就从cache中删除。
第二个问题是资源锁的问题,在存在并发的情况下,服务端必须锁定资源,如果不是带锁的cache,此时就要避免从cache中获取数据,以免脏数据。
注意:在多层cache的情况下,还需要考虑cache之间数据的一致性,而不仅仅是cache与数据库的一致性。
7. 每台服务器Cache的数据量评估
JVM内存cache要缓存多少数据,依据服务器内存【如果同时采用了本地文件缓存策略,就需要考虑准备在硬盘上钝化多少缓存数据】,cache对象的大小进行评估。远程cache能够缓存多少数据,依据内存【如果同时采用了本地文件缓存策略,就需要考虑准备在硬盘上钝化多少缓存数据】,cache对象的大小进行评估。
要进行评估,首先要计算出资源的尺寸【按照选择的序列化方式测量】。
计算每台服务器能够cache多少数据或需要cache多少数据才能够发挥cache的效果。在多机器环境下,对于JVM本地cache基本按照内存能容纳多少数据即可,如果同时开启了文件存储特性,可以按照资源活跃度来来粗略估计,在后期再依赖cache监控获得的数据进行精确调整。在远程环境下,如果采用单服务器模式,可以按照完全内存缓存的情况进行计算;对于cluster cache,目前还没有使用过,建议初期采用全内存方式进行计算。
8. 网络流量评估
在远程环境下必须评估网络流量/秒,以供SA参考。
9. Cache效能监控日志
在使用过中,会随时调整一些cache相关的参数,此时性能日志就非常重要。可以从2个层面获取日志:cache服务器自身的性能监控日志;业务系统定制的一些日志参数。
业务定制监控参数的一个简单例子:资源类型,会话数(Session ID),cache请求次数,cache命中次数,当前cache中数据量,数据库访问次数,平均访问时间。
10. Cache可用性监控
对于远程cache模式,需要提供相应的监控方案和通知方案。
11. 远程Cache可用性测试
-
考虑如下故障模式,是否对应用系统产生致命影响【主要是性能】:
- 本地cache不能正常使用
- 远程cache全部不能访问
- 其中1个cache服务器不能访问
- cache都不能工作时的性能指标等
12. 故障模式解决方案
Cache服务器故障时的解决方案,在确保系统可用的情况下,可以实施那些策略来度过难关。例如: 通过apache限制访问量。
13. Java环境,Cache如何与程序结合
-
在Java环境,可以通过如下方式实现结合:
- AOP方法拦截方式
- 面向属性方式
- Cache模板方式
- AOP扩展点方式
- 事件模式
- 代理模式
- 直接访问cache API
- 等
我选择代理模式实现查询和监控,事件模式实现数据更新。
14. 适度调整程序,以最优化cache效果
大部分情况,我们加入cache对应用层【相对于soa服务层】的影响很小。但某些时候,应用层的某些程序设计方式,数据获取方式,与cache结合的时候,可能会很不爽,甚至会导致成本过高。此时,不要死守某些所谓的原则,可以针对使用cache这种需要,适度调整程序,甚至某些业务的表现方式【只要业务本质不发生变化,程序上甚至可以违背某些API的原则—这些原则有时候,并未考虑特殊的cache使用需求】,以最优化cache效果。
【其它资料:】
Java开源缓存框架
使用Cache Farms和Read Pools提高Web应用的伸缩性
服务器的大用户量的承载方案 Nginx Squid Apache PHP MySQL
Declarative Caching Services for Spring
Spring Aop cache
youtube architecture
Golden rule of web caching
术语:性能、可伸缩性定义
Oracle’s Cameron Purdy Looks at 10 Patterns for Scaling Out — 该文虽然讲的是可伸缩性,但其中很多点也适用于性能思考过程,例如:“10 - Understanding the Problem,9 - Define the Requirements,4a - Plan for Overload,3a - Plan for Failure,2 - Tier Where It Makes Sense,1 - Simplify ”
可伸缩性最佳实践──来自eBay的经验—文中一条规则“适当地使用缓存”很重要,并不是每个业务点或架构层都适合使用缓存。
Trading Consistency for Scalability in Distributed Architectures —- 一致性与可伸缩性
利用 ThreadLocal 提高可伸缩性
Memcached使用点滴
这些都不是SOA
在和同事们讨论我们的服务化过程中,以及网上看到的一些帖子,甚至在某些SOA的宣讲会中,把以下情况都认为是在搞SOA:
- 使用web服务的应用就是SOA
- 使用RESTful的应用就是SOA
- 使用了分布式计算就是SOA
- 使用WS-*扩展的web服务应用就是SOA
- 使用了ESB产品,就是SOA
- 使用了SCA产品,就是SOA
- 使用了IBM,Microsoft等公司提供的SOA产品,开发出来的应用就是SOA
以上这些情况都不是SOA。SOA是以业务入口点,来自于实际的业务需求,以下例子才是真实的SOA。
XX航空集团开发的独立系统很多,现在需要把信息流整合起来,制作更全面的报表、提升信息流转的速度、方便信息分享、提高信息检索速度等,此时从业务信息整合的角度出发,以服务的思想构件了一个新的统一信息平台。
我们公司存在同样一个业务逻辑,会用在WEB平台,手机平台,管理平台,开放平台(还有其它原因,参考SOA,想说爱你不容易),原有的做法是共享类库,直接操作SQL等实现,现在利用SOA的思想,把这个业务逻辑封装为服务,供所有平台使用。
Yahoo中国和口碑合并,内部系统必然涉及到人员,业务流程的变化,采用SOA就能够化解之(我们常常看到一些报道,某公司收购另外一个公司,信息化系统的整合往往花费几年时间[当然还有其它原因,例如文化],甚至会失败。案例表明:采用SOA的公司,成功率高于不采用SOA的公司)。
参考资料:
http://www.infoq.com/cn/news/2007/07/soa-ws-relation
IBM提供的实践文章
IBM 内的 SOA 应用,第 1 部分: SOA 案例研究
IBM 内的 SOA 应用,第 2 部分: SOA 案例研究
IBM 内的 SOA 应用,第 3 部分: SOA 案例研究
IBM定义的SOA入口点:

ESB产品升级准备:SOA、ESB、JBI、SCA、OSGI概念再学习、再理解
这几日看了许多SOA,ESB,JBI,SCA,OSGI相关的书籍、BLOG、文章、JavaOne上的一些资料,希望在ESB产品升级之前,能对这些概念再次进行学习、理解。明确术语,确定关系。
SOA
-
SOA是一种业务建模思想,是一种架构风格;它以服务为核心,构建系统;通过进化控制节奏;【摘录】支持对业务进行整合,使其成为一种能够相互联系、可重用的业务任务或者服务。
- 一种业务建模思想
SOA是一种业务建模思想,而不是一种技术体系。它来自业务敏捷的需求,植根于业务,致力于提升业务的敏捷性。
最低层面:使用SOA的思想分析、重构业务,用服务的概念定义业务单元。实现层甚至使用现有技术体系,选择几种结构型模式:Façade模式,Proxy模式,Composite模式配合,从而达到原始的SOA层面。SOA并不强制我们必须分布,必须采用一些支持SOA的技术或产品,只要业务敏捷了,且当前技术架构也能够满足生产发展的需要,就是合适的。 - 一种架构风格
SOA也是一种架构模式,特别是一种分布式架构模式。
实践观点:第二个层面以第一个层面为基础,没有第二个层面,只有第一个层面,我们还可以说这个系统是SOA化的;没有第一个层面,只有第二个层面,这个系统是否SOA化,值得商议。(IBM提出的SOA切入点中,包含有以技术为中心的切入点【连通性】,从我们实践、公开案例的实践、专家有关SOA实践的书籍来看,以业务为切入点是最合适的,也是最容易成功的,获得组织支持的概率也大;单一的基于技术切入SOA架构,案例较少)
它的一些特征:
以服务为基本单元,可以把服务视为构件。
服务质量可度量,且可以提升。
基于开放标准。
该架构同时是一种分层架构。
具有分布的能力。
与技术无关性。
鼓励扩展。
支撑业务敏捷的要求。
架构层面主张组合。 - 服务设计的原则
松散耦合
服务契约
自治
抽象
复用性
组合性
无状态性
可发现性
互操作性
【注:此处的架构仅指技术相关的架构。】
ESB
-
ESB是一类中间件产品的通称;是一种分布式的技术架构,以中介为核心概念;是一种支持SOA实施的技术选择;来源于集成的需要,实现服务、系统之间的互联、整合;ESB产品通常提供一种容器,方便插入各类通用服务(编排服务、消息服务等)、提供服务虚拟化的能力(协议和模式、接口、身份等)、提供面向方向的连接(安全性、管理、日志记录和审核等);支持业务逻辑和实现的技术逻辑的分离。
-
它使用XML(可扩展标识语言)作为标准通信语言。
它支持Web服务标准。
它支持消息传递(同步、异步、点对点、发布-订阅)
它包含对服务编制(orchestration)和编排(choreography)的支持。
它包含智能、基于内容的路由服务(itenerary路由)。
它包含转换服务(通常是使用XSLT),在发送应用和接收应用之间转换格式,简化数据格式和值的转换。
它可以条件路由,或基于非集中策略的消息转换,即不需要集中规则引擎。
它提供对服务监控、治理相关的内容。 -
参考资料:
http://www.ibm.com/developerworks/cn/architecture/ar-esbpat2/index.html
http://www.ibm.com/developerworks/cn/architecture/ar-esbpat1/index.html
http://www-128.ibm.com/developerworks/cn/webservices/ws-esbscen/index.html
http://www.infoq.com/cn/articles/ESB-Roundup-Part1-Defining-ESB
http://www.ddj.com/java/201200303;jsessionid=DP5D5J5VEP4XKQSNDLPSKHSCJUNN2JVN?_requestid=459785
最常用到的特性:
JBI
-
【摘录】是基于面向服务体系提倡的方法和原则,为了解决 EAI 和 B2B 若干问题的 Java 标准。JBI 定义了基于插件方式的架构,以便服务能融入“ JBI 运行时”环境。 JBI 提供了详细的接口,使服务能与“ JBI 运行时”环境交互。
- 资料:
http://soaneu.blog.com.cn/index.shtml
http://www.jcp.org/en/jsr/detail?id=208
http://www.infoq.com/jbi
服务引擎、组件绑定图:

本图强调了服务引擎,组件的绑定方式,更倾向与产品的扩展。对业务级别的服务模型支撑比较弱,业务通过API来实现与JBI产品的交互。
SCA
-
服务组件体系结构 (SCA) 是一个规范;是一种架构模式;是一种通用的面向业务服务的组件模型;定义了部署模型;提供了实现提供服务和使用其他服务的组件、组装组件,以通过服务引用其他服务的方式来构建业务应用程序–与SOA组合的原则一致;SCA是平台无关的;SCA是一种编程模型;支持业务逻辑和实现的技术逻辑的分离;是一种支持SOA实施的技术选择;SCA支持组件的分布。
- 资料:
http://dev.yesky.com/topic/308/7667308.shtml
http://www-128.ibm.com/developerworks/cn/webservices/ws-theme/ws-soa.html#sca
http://www.davidchappell.com/articles/Introducing_SCA.pdf
http://www.osoa.org/display/Main/Service+Component+Architecture+Home
http://www.infoq.com/sca
http://www.infoq.com/articles/setting-out-for-sca
http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-41500&yr=2007&track=3
【摘录】is a set of specifications which describe a model for building applications and systems using a Service Oriented Architecture. SCA models solutions as sets of service components offering services and making references to services supplied by others, which are combined together by composites which wire references to services and which declaratively apply bindings for communication methods and also apply policies for aspects such as security and transactions. SCA extends and complements prior approaches to implementing services, and SCA builds on open standards such as Web services.
核心概念图:
本图强调了组件模型,服务组件之间的组合模式,把业务级别和系统级别的组件,同等对待。提供了业务组件接入容器的方式。完全符合SOA的概念。
OSGI
-
【摘录】一个开放并且提供统一接口标准的体系框架,基于这个体系框架,服务提供商,程序开发人员,软件提供商,服务网管运营商,设备提供商能够协调地联合起来开发,部署以及管理向用户提供的各种服务。
- 资料:
http://www.riawork.org/
http://www.infoq.com/osgi
http://www.osoa.org/download/attachments/250/Power_Combination_SCA_Spring_OSGi.pdf?version=3
http://xml.coverpages.org/OSGi-ServicePlatformOverview2004.pdf
http://www.blogjava.net/BlueDavy/archive/2007/10/14/152820.html
http://www.blogjava.net/hx9111/archive/2006/11/10/OSGi-SCA.html
http://www.blogjava.net/zhaobin/archive/2007/11/06/158485.html
【摘录】provides a service-oriented, component-based environment for developers, primarily on the
Java platform. It provides a dependency resolution mechanism, with version support and also offers standardized ways to manage the software lifecycle. OSGi is a particular boon when using different components that use different versions of some shared package. These capabilities greatly increase the value of a wide range of computers and devices that use the Java™ platform.
相互之间的关系
- SOA – ESB
ESB是一种支持SOA实施的技术选择。 - SOA – JBI
JBI是Java领域一种支持SOA实施的技术选择。 - SOA – SCA
SCA是一种支持SOA实施的技术选择。 - SOA – OSGI
没有直接关系,目的不一致。 - ESB—JBI
JBI和ESB是互补的。JBI提供一个模型和将集成组件作为服务的标准接口。JBI可以宿主在一个应用程序服务器环境或者在一个ESB容器中。ESB提供了一套基础架构包括了事件驱动的SOA,高度分布的路由目的地命名,企业消息能力和分布管理能力。 - JBI – SCA
【摘录】SCA has a strong model for defining composite applications、Services can be implemented in multiple languages、Can bind interfaces and references to different technologies。
JBI:Defines a standard, loosely coupled, ESB architecture、SE / BC are exchangeable between JBI implementations、Provides standard abstraction for all JBI components。
融合性:When combining JBI and SCA, all JBI service engines can be used in SCA components, SCA components can be called from JBI, SCA applications can be deployed as service units in a JBI container. - SCA-OSGI
相同点:都是一种规范;都是一种架构;一种编程模式;都定义了模块,服务概念。
不同点:OSGI强调模块的动态性;SCA强调服务的分布性;OSGI来源与单个JVM产品架构的需求;SCA来业务SOA化的技术需求;OSGI更适合产品架构;SCA更适合业务系统架构。
融合性:SCA可以作为Bundle部署到OSGI环境,以增强OSGI环境的业务架构解决能力;OSGI可以作为一个模块部署到SCA环境中,从而利用OSGI环境下的基础通用服务。 - SCA-ESB
相同点:都是SOA的一个可选的技术方案;都基于服务的概念;都是可分布的;都提供插件特性等。
不同点:SCA是一个标准,ESB是一个概念;SCA有模块的概念,ESB没有这个概念;SCA是一个组装车间,ESB是一个中介机构;SCA简单而清晰,ESB复杂而模糊,不同产品特性千差万别。
闲话SOA服务化之–接口和协议
在系统SOA化之后,不可避免的就遇到接口的问题,在Java环境使用XFire。常遇到:接口不匹配,服务依赖者不能动态切合等问题。
后来不知如何,就说起了银行的系统:多平台,多语言,物理分布,有购买的产品,有多开发商开发的产品,业务负责,存在协议(多是核心金融业务)、接口调用等多种方式。很是佩服之。随就接口方式和协议方式进行了一些比较。
【术语:
- 协议 — 协议包含了数据格式,同时规定了行为等方面的内容,例如邮件协议,RPC协议。
- 格式 — 对信息的编码。例如:XML格式。
- 接口方式 — 指程序接口调用实现业务交换的方式。例如:java API调用。
- 协议方式 — 通过某种报文(信息是满足格式的)实现业务交换的方式。例如:收邮件,发邮件。
】
| 比较点 | 基于接口 | 基于协议 |
| 开发人员编程期的易用性 | 容易理解
使用方便 可以直接编程 |
较难理解
使用较麻烦 不能直接编程 |
| 架构从单系统到多系统变迁的过程 | 平滑迁移 | 修改协议相关的代码 |
| 支持工具的方便、稳定性 | 有现成的工具,如xfire
稳定性很好 不需要考虑序列化问题 与Spring整合的非常好,程序员不需要关注序列化,传输,安全等问题 外界维护工具 |
可以使用xml binding1等工具1
需要考虑序列化问题 缺少一个类似这样的完整工具,让程序员爽 需要自己维护工具 |
| 自我校验 | 基于接口校验,例如 验证 工具自动支持 很容易自动方式检测不匹配性 编译时检查 |
基于协议校验,例如 schema验证 缺少工具自动支持 运行时检查 |
| 方法名称变更 | 需要变更,甚至重新发布系统(可以通过配置文件来避免重新发布) | 不需要变化
通常协议内部包含着业务指令号; |
| 方法参数变化(增加,减少) | 需要变更,重新发布系统 | 没有方法参数概念 |
| 方法参数类型变化(具体值得内涵没有变化,例如 123,从int变为string) |
可能会失败 | 没有方法参数概念 |
| 参数是对象类型,对象属性变化(增加,减少) | 增加不会失败,是否变化,依赖业务需求。如果业务上兼容该协议,那么也不需要变化;否则需要重新发布系统
这也是风险点(但可评估) 减少没有测试 |
没有对象参数概念 |
| 协议变化(增加,减少协议项)
(与) |
没有协议概念 | 可能会失败,依赖业务需求。
如果是技术上的一个协议项变化,那么可以不变化,也不会失败 如果业务上兼容该协议,那么也不需要变化;否则需要重新发布系统 这也是风险点(但可评估) |
| 增加方法 | 可能在自检查的时候系统级别失败
业务级别会失败 |
相当于增加了一个业务指令
系统级别不会失败 业务级别会失败 |
| 存在同名方法(参数类型不同,但相似)如( int和double |
会失败 | 没有该概念 |
| 工作流类、 JS类产品与业务结合的时候 |
需要引入多个接口
或使用动态 |
直接操作协议 |
| 一个业务的多个操作时的表示,例如:增,删,修改,查 | 通常是多个方法来表示不同业务 | 一个协议 +指令就可以解决 缺点:需要细心,别用错了指令(测试阶段可以解决) |
| 运行期稳定性问题 | 测试和系统检查可以确保运行起稳定性 | 需要很细心的测试和部分系统检查来确保运行期稳定性 |
| 接口变动太随意 | 由于容易,且是基于操作的,所以每个程序员都可以自由使用 | 由于复杂,而且是基于业务的,需要清晰、仔细的定义,反而因祸得福 |
| 管理方面 | SOA的相关支持工具,比如服务仓库,能够使用一种元语言完整地定义服务的契约,再根据这些元定义生成 一系列东西 |
缺少这方面的支持
需要自己开发相关工具 但产品经理可以通过业务层的管理来管理协议,从而约束开发 |
| 版本问题 | 解决较为麻烦 | 解决较为容易 |
| 与路由概念配合 | 较为麻烦 | 由于基于协议,与路由结合起来反而容易 |
| 投入成本 | 低 | 高 |
| 学习成本 | 低 | 较高 |
| 从实施工程的角度看 | 组织的软件成熟能力度要求低,项目管理要求中.开发人员人员水平偏低,更需要强约束的框架或者实现方式。 | 组织的软件成熟能力度高,项目管理要求中高 |
【说明:】虽然SOAP也定义了文档格式,但在实际使用中,使用者很少。毕竟,文档格式方式的WS走到是协议思路。
【闲话杂聊】
最近看到REST方式,它非常流行,很多网站的OpenAPI都基于它来搞,我们也准备尝试之。看了深入浅出REST一文,初步了解了一下它的资源概念,还是有些不知所措;又看到Building Web Services the REST Way一文,其中一句话“REST - An Architectural Style, Not a Standard”,指出了本质,原来我们可以在它的框架下使用接口方式,也可以使用协议方式。
结合它的目标是描述资源—互联网资源,我们就会发现,互联网界的大部分内容都是用协议来描述的,例如:HTTP协议,HTML协议等。 再看看google的RESTful API Specification,虽然是API,也基本是用半个协议的方式进行描述(它的JS标准部分,完全是接口的方式,毕竟这个时候不存在整合的需求。Facebook的API,也基本上接口方式,输入参数按照HTTP提交方式,输出部分到部分定义了格式。)
在开放互联网界使用的Rest + 格式方式 ==?协议吗【注:我看到axis在搞 Rest (序列化部分用XML格式),这东西和非Rest 的WS有哪些本质区别?】在企业内部是否依然也有很强的生命力?— 留给实践来检验吧。
【后感】
接口:内存调用 –〉RPC调用 –〉IDL系列(COM+,corba,RMI等)-〉SOAP系列 ,这一条发展线路基本是程序员主导。从抽象的角度看,程序员是不关心业务的,因此尽可能的让集成方法远离业务层,从系统层面解决之。
协议:EDI,ebXML系列,信用卡数据交换协议,国人搞得cebXML等等,这条线路基本是业务专家主导。从抽象的角度看,业务专家不关心系统如何实现,它更关注业务的标准化。
接口和协议看似两个简单的概念,但它们代表了两种系统整合思想,两种架构思路。他们有时候是对立的,有时候又是糅合的,很有些哲学的味道,对立统一规律(辩证法)。
服务化的行军中:Enum使用,快乐的痛苦
JDK1.5之前,一直使用类似apache commons lang中提供的Enum。
由于如下几个原因,换选了java Enum。
- 远程服务在序列化旧式的Enum时,默认是不支持的,需要单独进行定制。常用的WS,Hessian,XML绑定工具,都不能很平滑的支持,且时不时有些莫名其妙的故障。
- 在高并发的时候,存在性能瓶颈。这也是业务量上去之后,才发现的。
- 这个旧式的枚举在对象序列化的时候,有些偏大(同样的常量字段:350字节左右,java Enum 大概124字节左右–其实也不小呀),和其承担的角色不像匹配。
- JDK1.5提供的枚举,简洁,方便,序列化工具基本都支持。
新老枚举使用在了如下场景:
- 业务常量
- 错误代码
其实使用的场景还是很简单的,开始我们使用的很开心,很舒服,到后来,却有些苦涩了。
- 在我们SOA化的进程中,核心业务单元都独立起来了,核心业务采用服务-组件模式(聚合模式),产品层调用服务层,完成一次业务行为。在这个过程中,每个组件单元都有独立的业务逻辑,相互不干扰,因此就产生了不同的业务常量Enum,和错误代码Enum。后来发现,部分业务常量Enum的部分语义有差异,导致一个业务逻辑段内出现2种业务定义;最头痛的是错误代码,无法直接给产品层返回,如果返回字符串,在反转的时候,存在不清楚枚举类型的问题。
- 有些业务单元吸取了前次的教训,把所有的错误代码定义在了一个枚举中,用起来好似不错。唯一不爽的是:wsdl文件,居然把所有的枚举都给列出来。
- 在服务化不断进展中,出现了一个核心业务调用其它几个核心业务,这最外面的服务痛苦不堪,它的处境与情况1相似。
- 由于某个偶然的原因,还出现了A程序用b1,b2,b3枚举来详细区分业务,B程序用b来区分业务,产生了b={b1,b2,b3}的业务语境,由此出现了二维枚举定义法。
- 老的枚举实在太多了,只好保留,产品层采用枚举转化化。最头痛的是:核心业务重新梳理之后,增加了许多常量和错误代码,产生了不一致的情况。
在使用过程中,WEB层又提出了一些特殊要求:下拉框,复选框,都需要提供复杂的枚举,例如{name,value,msg,sequence},实际使用的复杂度,超出了原始的常量要求。这些枚举就在我们的SOA环境中生存了下来,Happy的传来传去,有些随意的在多个系统之间溜达。
一直梦想JDK的Enum类能够提供如下方法,最后,只好自己搞一个了:
public static <T extends Enum<T>> T getEnumByName(Class<T> cls, String name);
public static <T extends Enum<T>> T getEnumByValue(Class<T> cls, String value);
public static <T extends Enum<T>> List<T> getEnumList(Class<T> clazz);
public static <T extends Enum<T>> List<String> getEnumNameList(Class<T> clazz);
public static <T extends Enum<T>> Map<String, T> getEnumMapKeyIsName(Class<T> clazz);
这个过程中有好些不合理的地方,仍需解决:
- 大规模SOA化业务过程中,业务常量的定义,使用Enum,是否是一个好的选择。好处:程序员比较容易找到;常量比较清晰,不容易出错;管理起来方便;变化周期较长,系统也允许重新发布;对分析、设计人员的要求相对较低,程序员可以方便的增加,变更业务常量。痛处:上面提到了一些,特别是最外围的聚合业务,有些不爽,产品层最是不爽。
- Enum作为服务接口参数,在跨越系统边界的时候,变相增加了系统的耦合度。
- Enum在域对象中适用,该域对象作为服务接口参数传递,在某些序列化方式下,会出现错误。特别是xfire的序列化,支持的很不好,如果域对象中还用Map<Enum,T>之类的,也会出现错误。此外,在open的服务接口中,可能出现其它语言不支持Enum概念的情况,因此在服务接口处,尽可能用原子类型;不爽的是,枚举的某些限制作用就会丧失,在程序内部可能出现大量比较、反转的情况。
- 错误代码,定义为枚举,不爽,但好处和第一条一样。比较HTTP协议,信用卡标准等,可见我们在业务协议标准化层面还有得发展,如果内部业务之间的协议标准化了,那么我们的SOA,可以进行的更好,我们的产品经理,甚至可以通过这些常量,代码,协议的维护,实现对产品的可控性。
- 二维枚举要避免。这其实也是业务没有能够标准化,一不小心就产生的变异。特别是第一个版本的业务设计,对后续的影响很是深远,从另一个层面表现出来的是:数据完整性发生了变化。可喜的是,说明了业务发展飞快;可忧的是,业务架构越来越要求具有前瞻性,扩展性,否则大家都很痛苦。
- 业务常量,大都具有很强的业务语义。定义的准确性,合理性,对后期的维护有很大的影响。跨业务功能单元的局部重叠的业务常量,表现起来(用Enum定义)痛苦,使用起来也痛苦。如何使好呀?
- 新老枚举共存为后续的痛苦,埋下了伏笔。
- 一旦服务开放了,又可能存在一层映射。
- 不用Enum,尝试某几个常量不用Enum,开始用起来很爽,测试维护的时候,傻了,这个常量是1,2,3;大于10个地方用到了,后来发现一个BUG,不能确定常量的业务语义了。特别是其它人阅读代码的时候,一头雾水。只好重新用Enum来定义,无论理解,维护都方便了。
- 规范化枚举的格式,开始定义枚举,有多种方式,直接定义:EnumName、带转义值定义:EnumName(value)、带文本说明的定义:EnumName(value,message)。各自都很不相同,后来有做管理平台的哥们用的时候,发现很不爽,想写个Utils都不行,还不能满足要求。最后同意格式:EnumName(value,message,扩展值),EnumName表征业务,value是实际数据值(如果本身就和EnumName相等,那么也要写之),message是说明文字,枚举构造器后面的参数业务自己定义。这里面,最怪异的是message,为了方面,直接用中文了,而没有用resourceBundle之类的技术,留待以后解决之。
SOA,想说爱你不容易
今日看到eBay的一篇架构实践文章,想起了最近1年,我们公司向SOA迈进的一些方面。
驱动我们公司进行SOA的原因思来有如下一些方面:
- 代码增长太快,系统地扩展性太差;开发过程中,往往由于一个小的变动,就会重新发布整个系统
- 系统庞大,功能错综交叉,还在不断的堆积新功能,耦合度递增
- 业务部门对敏捷性的要求,市场是变化的(市场变化的速度加快了,竞争对手创新的速度也加快了),产品也需要能够适应变化
- 业务需求增长太快(市场变大了),同时进行的并发项目太多,非但进度缓慢,而且代码合并,集成测试都带来很大挑战;而且许多需求被压制,引起业务部门的不满意
- 一个系统容易掩盖业务的本质,使我们不能很好的分离业务逻辑和产品(一个业务逻辑,可以使用多种包装方式形成不同的产品,例如:登录业务,可以由weeb登录产品,wap登录产品,终端登录产品,接口登录产品等。)
- 把一些本来属于产品特有的逻辑也混杂在业务逻辑中,使得业务本质模糊,代码丑陋等等
- 每次启动工程都需要2-5分钟,所有人都已经不能忍受
- 系统发布计划越来越复杂,发布频率越来越高,稳定性变得越来越不可控
- 组织结构频繁变动
- 业务核心随着战略的变化,逐步演变;系统由单一核心业务向多个核心业务为中心的模式展开
- 随着销售的引入,产品化的需求变得很强烈
- 管理制度发生了变化,条例(安全相关、行业法规相关,法律相关)更加严格,细化
- 计划引入项目成本考核,目前状态下的成本明显偏高,架构必须为成本的降低做出贡献,提高资源生产率
- 业务监控,管理的需求提上了日程
- 各种规则、架构约束力的作用日渐消弱,系统逐步向混乱的方向演变。
- 业务系统和管理系统存在两套代码的现象,增加了业务逻辑不一致的几率,代码维护成本(例如Fix业务BUG)随着业务的复杂递增,测试成本也随着递增
- 开放平台战略的确立,要求业务必须标准化,服务化
- 等等
当然了,我们架构组自身也实在无法忍受。
采取如下策略,历时一年,逐步SOA化(社会主义初级阶段)。
1、首先进行业务的服务化,把我们的系统划分为几个核心业务块,然后挑选其中的一块业务(例如:会员相关业务)进行服务化,逐步把几大业务搞定。
2、第一块业务服务化的同时,研究相关的基础技术。例如:ESB、分布式事务、OSGI框架、开发模式、系统部署模式、业务用例如何向系统用例转化、业务粒度的设计原则等。同时研究对立部署业务单元对性能、可靠性、稳定性方面的影响。
3、随后服务化的时候,引入可靠异步模式,包括业务流程异步化。
上面的过程和eBay架构实践中介绍的几点有一些相似性。
Scalability Best Practices: Lessons from eBay一文
- Best Practice #1: Partition by Function
- Best Practice #4: Decouple Functions Asynchronously
- Best Practice #5: Move Processing To Asynchronous Flows
在我们进行SOA的过程中,我们初步实现了按照大的业务快进行切分,还未能够实现对更细的功能点进行梳理。一方面是为了避免风险,另一方面我们也未能从业务上搞清楚再细粒度的功能点如何划分。
4,5两个技巧提到异步,在这二点上我们进行了一些有益的尝试,但还是未能破除目前太多的同步调用现象。究其原因,我们未能从业务上定义清楚更细粒度的功能点,以及它们之间是否适合异步。
从目前实践效果来看,我们解决了当时驱动我们SOA化的一些方面,同时引入了如下困难:
- 测试的困难,每次项目分支,由于其依赖其它业务核心,导致需要同时切出多个分支,申请多套环境
- 开放的困难,很多程序员不能理解这次调用到底访问的是谁?
- 版本问题
- 服务的监控和管理
- 最头痛的是:业务服务思想的延续性,已经出现部分业务核心偏离了当时的业务分类原则
- 产品层存在粒度过细的信息查询,没有考虑到SOA场景下,产品层信息使用的策略
- 技术体系相对复杂化了,开发、测试需要重新学习这种架构
- 等等
关于业务异步化:从长远来看,业务异步化的研究,会给我们的产品化、开放化、SOA化、网格化计算提供有力的支撑,同时显著提升我们系统的扩展能力。但从另一个方面来讲,它给我们的程序员,业务分析人员带来的困惑也会更多。
