服务的实例管理问题,一般有SINGLETON和SINGLECALL等方式。推荐采用SINGLECALL方式,如果服务具有状态的话会大大增加服务的开发难度,一是需要考虑线程同步问题,二是需要考虑生命周期。其实,我一直觉得有状态的服务配合ORM数据访问层的使用是很好的,但做起来可能会遇到很多问题。
在存储过程中做事务还是很简单的,SOA如果要做分布式事务的话,实现不是打大问题,但性能是很大的问题,很容易引起数据库对象的死锁。大多数情况下我们对分布式事务的替代方式是采用队列,放到队列中的东西就认为是一定可以成功的,对于不使用队列的情况,如果调用失败了则记录日志,不会进行回滚。除非涉及到钱的地方才做分布式事务。
版本问题也是需要考虑的。传统的实现方式是,如果新增接口的话以前的程序是没有影响的,如果万不得已需要修改接口的话就大吼一声,我这个接口要改了,然后给大家发一份,请调用者按照我的要求修改一下,连同我的服务一起重新发布。对于WCF的话,有MEX元数据交换,这样就不用手动引用新的契约,只需要从HTTP地址上更新新的服务即可。但有一个不得不考虑的问题就是万一在调用其它服务的时候发生错误了,我们怎么知道是哪个服务的版本出现问题了呢。我们是这样做的,调用服务的代理有一层封装,如果网络调用发生错误的话,会记录详细的错误信息,哪个服务(服务的版本)、哪个方法在哪个端点上的调用、传入的参数是什么,返回的是什么。这样,在部署的过程中发生错误或是版本问题,我们就很容易知道错误的原因了。那么怎么知道服务的版本呢?没一个服务都约定有一个GetVersion方法,这个方法两个作用,一是给管理工具测试这个服务是不是还有效,二是给配置服务获取服务的版本号。
如果引入SOA的话,不可避免的是大大增加了整个系统的部署复杂性。想一下,在LIVE上,我们可能有20个WEB服务器,10个APP服务器(我们以前是2:1这样进行配置的,服务按照类型和资源不同放在不同的APP服务器,WEB服务器CPU特别强,APP服务器是廉价服务器,有足够大的内存,对于WEB程序来说确实没什么大的CPU计算,服务也就是缓存比较厉害)。10个APP服务器上放100个服务,就产生了100个端点地址。开发人员其实不用考虑服务在LIVE上怎么部署的,需要架构师在部署的时候协调部署团队一起完成部署工作,架构师知道哪个服务部署在哪个服务器最合理,以哪种信道进行部署最合适。部署团队需要对各个服务器的结构很清楚,也要学会使用健康监控工具(我前面提到的监控服务运行状态的工具和异常管理工具来发现部署上的问题),这就对部署团队的要求更高了。实在不行的话可以要求开发人员参与,开发人员应该没权限直接进行服务的部署,但是有权使用两个工具的,一来用于排查问题,二来也会有很大的成就感。
服务监控工具以一个拓扑图形式展现整个网络上WEB服务器、APP服务器的IP地址、CPU内存使用,以及服务的引用情况和每一个服务对CPU和内存的占用,以及服务的健康情况。监控人员24小时值班负责监控,出问题的时候及时重新启动相关服务。异常管理工具每天收集各个系统的异常,开发人员每天上班和下班的时候查看一次这个工具,知道自己负责的模块产生了哪个异常(异常有几种,一种是程序有BUG,一种是外部有人在攻击造成的,还有一种是前面说的服务的版本和运行问题产生的异常)。当然,架构师也应该时刻关注这2个工具,知道整个系统的健康情况。
从网络上来说,APP服务器应该跨2个网段,DB服务器应该外部不能直接访问,所有数据库操作都是通过APP服务器提供的服务访问DB的,网站不具有任何连接字符串不能直接访问DB服务器(不在同一网段)。WEB服务器和APP服务器之间应该走TCP,如果是跨国的话应该有VPN链路。
从软件架构上来说,我们以前使用的是.NET Remoting对内,Web服务对外的方式,中间层以Windows服务作为载体。对于.NET 3.5时代,可以采用WCF+Windows服务承载的方式。WCF支持元数据交换是一个优点,另一个优点是方便TCP/HTTP各种绑定的切换,当然也可以同时提供多份绑定。如果是细粒度服务的话,可以使用ADO.NET DATA SERVICE+ADO.NET EF的方式直接进行提供。表现层可以直接使用ADO.NET DATA SERVICE也可以使用自定义的JSON/XML数据,不属于SOA的范畴就不扩展了。
总结一下:
对于ETOWN的应用,SOA架构是绝对适合的。
文章来源于领测软件测试网 https://www.ltesting.net/