WCF与Asp.Net Web Application的深度整合方法

在开发实践中,一种常见的情形是:先按照典型的方式开发了一个asp.net web application, 后来因为某些原因(例如,希望为其增加通过手机客户端操作的功能),希望为其增加更多的访问方式,当然,这时候服务端的解决方案当然首选WCF.

但是,如果将WCF与现有的web application进行合适的整合,需要慎重处理.同样的操作,通过普通的Web Service模式和原来的应用程序内部调用相比, 性能可能会下降数十倍甚至更多,而这种性能的大幅度下降是我们所不希望看到的.

为了在提供Service访问接口的同时,不降低现有的系统性能,亦不破坏原有的系统架构,我采取了如下的方案:

1. 将WCF服务内嵌到Web Application项目中.

选择将WCF服务嵌入到Web Application中(而不是另外新建一个项目), 有两重目的:

(1) WCF服务可以直接调用原WebApp中的功能,而不需要通过复制代码,或是破坏原有架构的方式来实现. 复制代码可能带来一系列的不利后果,这个不再冗述,改变原有的WebApp架构则带来高昂的成本,或是进一步的性能下降.

(2) WebApp自身不再需要通过任何一种channel来调用WCF功能, 它可以像使用一个普通类那样直接创建一个服务类的实例, 并调用其方法. 这一点很重要. 实际上,服务的主要使用者还是WebApp, 或者说, 如果不考虑增加客户端的种类,根本就不需要引进WCF,这些功能本来就是WebApp的一部分. 而如果将这些功能从WebApp中完全独立出去, 势必造成WebApp去访问服务时, 需要通过某种channel来进行通讯, 而这必然会带来一定的性能下降, 对于有些高频度使用的功能来说, 这可能会带来非常明显的响应速度障碍. 而通过将WCF服务嵌入到WebApp项目中,则完全消除了由于引入WCF而带来的对WebApp自身造成的性能影响.

操作方法:

直接在VS中添加新项—>WCF Serivce 即可.

另外, 在Web.config中要增加相应的Service配置: 在根节点<configuration>下增加<system.serviceModel> 节点(如果已经有了...那你就不用添加了...), 其配置内容如下:

<system.serviceModel>
  <services>
    <service name="Goodbaby.TestService">
    </service>
  </services>
</system.serviceModel>

其中,Service的name取决于实际项目的命名空间和服务类名.

2. 开放Named Pipes channel, 使得托管在同一台服务器上的其它应用程序可以可以通过named pipes访问WCF服务.

Named pipes channel是WCF的各种通讯方式中性能最高的一种, 但是它只能被同一主机的另一个应用程序所调用. 如果在实践中该服务器上只部署了这一个应用程序, 则可以忽略这一节. 但是如果在服务器上还部署了其它的应用程序, 并且它们有访问WebApp功能的需求, 则使用Named pipes就是最佳选择.

在WCF中, 通过netNamedPipeBinding来实现Named pipes channel, 因此只需要配置一个使用该Binding的endpoint即可.

操作方法:

在Web.config的service节点下, 添加相应的endpoint, 配置内容如下:

<service name="Goodbaby.TestService">
  <endpoint address=""
            binding="netNamedPipeBinding"
            contract="Goodbaby.ITestService">
  </endpoint>
  <host>
   <baseAddresses>
     <add baseAddress="net.pipe://localhost/WebApp/WebService/TestService.svc"/>
   </baseAddresses>
  </host>
</service>

这里在上面添加的service下面又添加了一个endpoint节点和一个host节点. 其中, endpoint中未指定address, 代表它将使用baseAddress, binding设置为内置的netNamedPipeBinding, 而contract是WCF服务所使用的接口名.

baseAddress中,net.pipe表示这是一个Named pipes channel, 由于该channel只能在本机调用, 所以它的主机地址应该总是localhost, WebApp是实际的应用程序名, 后面的WebService是项目中的一个文件夹名, 而TestService.svc则是WCF服务所在的文件名.

在IIS上启用named pipes(net.pipe binding)支持

本来,在web.config中完成配置后就可以测试服务了,但是IIS默认是不支持net.pipe binding的,所以需要进行以下步骤以启用.

(1)打开控制面板—> Turn windows features on or off—>Microsoft .Net Framework 3.5.1(这个版本号取决于实际安装的版本), 勾选Windows Communication Foundation Non-HTTP Activation, 保存.

(2)选中IIS的Default web site(或是其它的自己添加的网站),在右侧的Actions面板中点击Bindings(如下图:).

image

在弹出的面板中确认是否已经添加了net.pipe binding:

image

(3) 展开Default web site, 点击选中具体的web application名, 在右侧的actions面板中点击advanced settings, 如下图:

image

在弹出的设置面板中确认Enabled Protocols是否包含了net.pipe.

(4) 重置IIS.

如果完成上述设置后, 仍然不能正常浏览服务, 可能需要重置iis.

打开一个cmd命令窗口, 输入以下命令:

>cd\windows\microsoft.net\framework\v4.0*

最后一个目录是版本号, 请按实际安装的版本号为准.

然后执行aspnet_regiis –i

执行完成以后, 执行iisreset

(5) 在IIS中浏览服务.

在IIS的Content View中选中WCF服务文件(TestService.svc), 右击, Browse, 应该会看到默认的服务浏览界面:

You have created a service.

To test this service, you will need to create a client and use it to call the service......

3.对于局域网中的用户,尽量采用TCP channel来访问WCF 服务.

TCP channel的性能大约比普通的http快十倍左右, 在服务端要启用tcp channel与上述的named pipes非常类似, 增加一个endpoint, 并且在IIS上开启相应的支持即可, 具体做法由于与第2节极为相似, 不再详细说明.

4.HTTP channel也应当保留

典型的HTTP channel(也就是一般意义上的web service)虽然性能较差,但是其穿越防火墙的能力和通用性上的优势是其它channel所不能比拟的,当前面几种channel都不能使用时,应当使用http channel与WCF服务进行通讯.

其具体的实现方式与其它的binding亦非常类似, 而且也是各种资料里提及最多的, 这里不再详细列出.

总结

借助于WCF对通讯方式的整合, 当实现多种访问渠道时, 对项目的实际修改只是在web.config中增加endpoint(及相应的对binding的配置,如果需要的话), 这使得无论通过什么方式去访问WCF服务, 甚至于不把它当作一个服务, 而是直接作为项目的一个类来看待, 执行的都是相同的代码, 这避免了将同样的功能复制好几份存储于不同的项目中,同时也保证了在各种上下文中都达到性能的最优.

---------------------------------------------

作者:夏狼哉
博客:http://www.cnblogs.com/Moosdau

如需引用,敬请保留作者信息,谢谢

原文地址:https://www.cnblogs.com/Moosdau/p/2788956.html