本文目的

需求变化是软件开发过程中的一大难题,我们经常扼腕叹息:面对变化,我们的软件为何如此不堪一击?我们常常在众多需求变化导致的功能爆炸中疲于奔命,甚至迷失自我!这到底为什么?面对"拥抱变化"这种得呐喊,我们的感受应该是震耳欲聋,还是振聋发聩?如果你仍在困惑,可以来看一看WCF是如何摆脱这种困境的!

序幕

小王效力于北京的一家系统集成公司,该公司内部有一个WCF服务为各个部门所共用,小王便是WCF服务的开发和维护人员。起初大家在一个办公楼工作,共用一个局域网,WCF运行的非常好,小王也因此获得了公司上下的一致好评。此时他们的WCF的使用状态如下图所示:

起初小王以为公司都在一个局域网之中,考虑到性能,WCF最早采用的是NetTcpBinding的绑定方式,契约部分是根据自己的业务需要开发的, 而他为服务公布的最早的地址为:net.tcp://127.0.0.1:6547/Service。他最早是用代码方式将服务托管到一个Console程序中的,托管代码如下:

ServiceHost host = new ServiceHost(typeof(ServiceLib.Service)); 

NetTcpBinding bind = new NetTcpBinding(); 

Uri address = new Uri("net.tcp://127.0.0.1:6547/Service"); 

host.AddServiceEndpoint(typeof(Contracts.IService), bind, address); 

而此时大家所使用的客户端代码均为:


NetTcpBinding bind = new NetTcpBinding(); 

EndpointAddress address = new EndpointAddress("net.tcp://127.0.0.1:6547/Service"); 

Proxys.IService ws = new Proxys.ServiceClient(bind, address); 

这样一种情况下,小王的WCF服务与各个部门之间可谓是其乐融融。可好景不长。各位看官,请看下文:

使用范围扩大

随着近几年公司业务的持续发展,公司在唐山的业务量非常大,所以在唐山成立了一个办事处,而该办事处同样需要使用小王的WCF服务,可原本出乎小王意料的事情发生了:唐山办事处和公司总部处于不同的网络,如果还使用tcp这种传输方式,就不适用了。公司头们为这事也挺犯愁,本来以为还要劳烦小王大改一通,没想到小王却说:"小意思,马上解决问题!"他首先和公司网络管理人员联系,将WCF服务所在主机配置1个公网IP为202.120.120.3,然后再托管程序的代码中增加几行

BasicHttpBinding bind = new BasicHttpBinding(); 

Uri address = new Uri("http:// 202.120.120.3:80/Service"); 

host.AddServiceEndpoint(typeof(Contracts.IService), bind, address); 

然后将客户端程序场景中的代码修改如下:

BasicHttpBinding bind = new BasicHttpBinding(); 

EndpointAddress address = new EndpointAddress("http:// 202.120.120.3:80/Service"); 

Proxys.IService ws = new Proxys.ServiceClient(bind, address); 

然后将托管程序重新发布了一下。而将修改之后的客户端部署到办事处一台服务器上面,经过测试,新的客户端运行正常,而总部那些客户端也没受任何影响。由此可见,双方相安无事,小王也松了一口气,原本另大家比较头疼的变化问题便迎刃而解了。下面是使用范围变化之后,WCF服务与客户端的工作情况:

停电了,殃及池鱼

昨天请假了,今天兴致勃勃来上班,没想到刚来,却被经理劈头盖脸的数落了一顿:" 昨天停电,来电后,你的服务没有启动,打你电话也不接,下次注意亚!",小王抓抓了头皮,不好意思的笑笑说:"好,我马上想办法,防止出现类似问题",回到座位上,小王就想到了用iis来替代console作宿主,这样机器重新启动后,服务便会自动加载,可转念一想,不对,iis支持http的访问方式,而且基地址必须和服务所在网站地址一致,我们局域网内部采用的是tcp,排除了iis,小王很快就想到了windows service,恩,就它了。所以问题也便成了下图所示的情形:

经过查证,小王先弄明白了下面的原理:

不仅如此,在不同宿主中寄宿的方法也一致:都是采用ServiceHost来进行托管。知道上面的知识,小王将原本Console宿主中 的托管代码拷贝到Windows服务的代码中,只不过,Console中托管代码写在Main方法,而Windows Service写在OnStart方法中。

秀才遇见兵

原本只是公司内部使用的WCF服务,前段时间也开放给了公司的几个大的合作商,和他们的平台作整合,前几家,合作的非常好,小王正津津乐道之时,却遇到了一个刺头,他是公司一个非常重要的合作商,但要求也非常特殊,服务中原本有个数据契约,用于描述公司订单,契约的定义如下:

旧版本数据协定
[DataContract] 

public class Order 



private string _orderID; 

[DataMember] 

public string OrderID 



get 



return _orderID; 



set 



_orderID = value; 





private string _content; 

[DataMember] 

public string Content 



get 



return _content; 



set 



_content = value; 







而且其他的合作商,对此都没有任何的异议,小王将代理已经发出去10几家了,可现在遇到这位要求必须再上面的基础上再提供订单的创建时间,小王打电话过去,和他解释:"目前我们的系统已经被很多厂商使用,而且别人的代理目前也运行的很好,你的这个需求是正确的,但我们如果修改数据契约会影响其它客户端的使用,请理解",本以为自己苦口婆心的解释,人家会买账,谁想,对方根本不听解释,一个劲地说:"这是我们的需求,必须的,必须的!"。气得小王直想摔电话。可"用户是上帝,胳膊扭不过大腿么",后来一高人指点道:"WCF在设计的时候已经考虑到了版本管理的问题,这种问题已经非常容易解决,你可以用IExtensibleDataObject",经查阅还真有此类问题的解决方案,小王将上面的契约代码更改如下:

新版本数据协定
[DataContract] 

public class Order:IExtensibleDataObject 



private string _orderID; 

[DataMember] 

public string OrderID 



get 



return _orderID; 



set 



_orderID = value; 





private string _content; 

[DataMember] 

public string Content 



get 



return _content; 



set 



_content = value; 





 

private ExtensionDataObject _exData; 

public ExtensionDataObject ExtensionData 



get 



return _exData; 



set 



_exData = value; 





 

private DateTime _createTime; 

public DateTime CreateTime 



get 



return _createTime; 



set 



_createTime = value; 







然后新生成一个代理,发给了刁蛮用户,而其他客户的代理版本却不用任何变动。新的用户的代理运行和很正常,而老的也很正常,真爽!小王此时方体会到WCF的强大之处。

凡是符合下面的变动情形的,均可视为非重大更改:

  1. 更改成员名称,且将DataMemberAttribute的Name属性和旧版本保持一致
  2. 大多数添加和移除数据成员的操作
  3. 将成员的特性IsRequired从True更改为False
  4. 实现IExtensibleDataObject接口
  5. 更改枚举成员名称,但用EnumMemberAttribute将协定名称和老版本保持一致
  6. 大多数数据集合的更改

服务也会累么?

问题是一个接一个,解决完上面的几个问题没多长时间,这个WCF又有新问题了,现在客户端越来越多,很多客户反映,最近服务端很不稳定,有时还连接不上去,小王检察了半天业务代码,发现没有问题,而且之前人数少得时候,运行的挺好的亚,此时他经过仔细的查阅,终于找到了一些用的信息:WCF为了改善性能,是有限流(Throttling)措施的。主要包括三种

  1. maxConcurrentCalls :最大并发数,默认为16
  2. maxConcurrentSessions :最大的会话数,主要针对于PerSession的情况,默认为10
  3. maxConcurrentInstances:最大实例数,默认为Int.MaxValue

默认的设置比较保守,最大并发数仅为16,非常容易造成排队或者超时现象。修改或者添加限流也非常简单,只需要在服务的配置中修改或者增加ServiceBehavior中的

<serviceThrottling maxConcurrentCalls="16" maxConcurrentSessions="10" />

后记

拥抱变化,拥抱变化,我们口号喊得非常响亮,可为什么面对变化的时候,我们有时会暴跳如雷呢?一边骂客户bt,一边还要通宵达旦的加班来完成工作呢?问题的原因不在于用户,不在于变化本身,更多的是我们一味的将一堆垃圾改造成另外一堆垃圾,要想真正解决问题,做好架构,做好基础是关键。我们常常因为时间,人力等因素,刹不住车似的的制造garbage,却忘记了什么叫细节,什么叫品质。无论针对产品还是市场,当前更重视不是你做了多少,而是做了多少有意义的事情,多少别人没有做过或者做不了的事情。品质,细节,ThinkPad,Google。总之我会毫不犹豫地转向WCF,因为它有品,也更能适应变化

WCF从理论到实践(15):响应变化相关推荐

  1. 艾伟:WCF从理论到实践(11)-异步

    本系列文章导航 WCF从理论到实践(1):揭开神秘面纱 WCF从理论到实践(2):决战紫禁之巅 WCF从理论到实践(3):八号当铺之黑色契约 WCF从理论到实践(4):路在何方 WCF从理论到实践(5 ...

  2. 艾伟:WCF从理论到实践(2):决战紫禁之巅

    本系列文章导航 WCF从理论到实践(1):揭开神秘面纱 WCF从理论到实践(2):决战紫禁之巅 WCF从理论到实践(3):八号当铺之黑色契约 WCF从理论到实践(4):路在何方 WCF从理论到实践(5 ...

  3. 艾伟:WCF从理论到实践(3):八号当铺之黑色契约

    本系列文章导航 WCF从理论到实践(1):揭开神秘面纱 WCF从理论到实践(2):决战紫禁之巅 WCF从理论到实践(3):八号当铺之黑色契约 WCF从理论到实践(4):路在何方 WCF从理论到实践(5 ...

  4. 艾伟:WCF从理论到实践(13):事务投票

    本系列文章导航 WCF从理论到实践(1):揭开神秘面纱 WCF从理论到实践(2):决战紫禁之巅 WCF从理论到实践(3):八号当铺之黑色契约 WCF从理论到实践(4):路在何方 WCF从理论到实践(5 ...

  5. WCF从理论到实践(14):WCF解决方案模板 (转)

    WCF从理论到实践(14):WCF解决方案模板 正所谓磨刀不误砍柴工,虽然VS2008为我们提供了WCFServiceLibrary项目模板,但在实际开发的时候,我们通常更喜欢按照自己的方式来建立WC ...

  6. WCF从理论到实践(5):Binding细解(转)

    WCF从理论到实践(5):Binding细解 本文的出发点: 通过阅读本文,您能了解以下知识: WCF中的Binding是什么? Binding的组成? Binding Element 的分类? Bi ...

  7. WCF从理论到实践(10):异常处理 (转)

    WCF从理论到实践(10):异常处理 本文目的 通过阅读本文,您能理解以下的知识 1) WCF中存在哪几种异常处理方式? 2) 各种异常处理所适用的应用场合? 3) WCF中常见的异常类型? 4) 代 ...

  8. WCF从理论到实践(17):OO大背离(带视频+ppt+源码)

    如果您懒得看下面的文字,您按下面的提示下载视频教程,里面还有ppt和源代码 请您到:http://downloads.cnblogs.com/jillzhang/wcf17.rar 下载视频+课件+源 ...

  9. WCF从理论到实践(4):路在何方

    本文的出发点 通过阅读本文,您能了解以下知识: Address是什么? Address的组成? 如何在配置文件中指定Address? 如何通过编程方式设置Address? Address有什么特殊应用 ...

最新文章

  1. 【译】微软出品HashiCorp Terraform 和 Vault 系列视频
  2. AIX和linux SSH互信
  3. oracle经典增删该查,oracle基本语法(增删改查
  4. 博士生的经验就要传下去
  5. C语言 Hello World - C语言零基础入门教程
  6. 性能计数器驱动_【Nature Sustainability】机械力驱动的摩擦电高效空气负离子发生器...
  7. WPF TreeView 相关技巧
  8. 基于Docker搭建Jumpserver堡垒机操作实践
  9. QtCreator 编译时提示 warning C4819 的解决办法
  10. php 循环 post,如何在php中使用jQuery递归调用POST循环请求
  11. Linux下vsftpd的安装,Java上传文件实现。
  12. tomcat中server.xml文件解析
  13. 好文章推荐 数据库mysql
  14. mysql源码启动_mysql源码分析-启动过程
  15. 腾讯手游助手吃鸡一直服务器繁忙,腾讯手游助手里的吃鸡鼠标移动太快怎么办?...
  16. kafka集群搭建并验证(个人亲手搭建,真实有效)
  17. 关于尾注的一些问题-上
  18. dfuse for EOSIO v0.1.0-beta4 版本更新说明
  19. 【GitHub】GitHub上指定文件夹轻松下载
  20. centos7 分辨率修改_centos系统修改屏幕分辨率问题

热门文章

  1. mysql表分区和表空间_mysql分表和分区的区别浅析
  2. petalinux2020.1 uboot 无法正常加载的问题
  3. mysql存储过程表_mysql 存储过程,表
  4. 鸿蒙智慧屏安卓内核,一切都是假象?荣耀智慧屏翻车,鸿蒙只是安卓的皮肤?...
  5. python高级语言应用报告_Python 语言及其应用 - 第一章
  6. lingo 嵌套@for或嵌套@sum
  7. 如何解决notefirst的闪退问题?
  8. 中国公有云三巨头,同时支持Rancher Kubernetes平台
  9. Vimium - 让Chrome高效工作的神器
  10. Ant编译编译APK、打包打包JS