Apply SOA Design Patterns with WCF (2) WCF Automatic Deployment (自动化部署)

本文介绍了一种简化WCF服务自动化部署的方案,利用配置集中管理与IIS特性来减少部署复杂度,实现跨多服务器环境的一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Original (原创) by Teddy’s Knowledge Base

Content (目录)

(1) WCF Configuration Centralization (WCF配置集中管理)

(2) WCF Automatic Deployment (WCF自动化部署)

(3) WCF Automatic Service Locating (WCF自动化服务定位)

(4) WCF Database Paging & Sorting (WCF数据库分页和排序)

(5) WCF Based ASP.NET DataSouce Control (基于WCF的数据源控件)

(6) 1 + 2 + 3 + 4 + 5 = ?

English Version

摘要

本文提供一种简化在多服务器和服务器群上自动化部署WCF服务的方案。

正文

什么是自动化部署?

自动化部署指自动化地部署一个应用程序到它的运行环境。一般,通过创建批处理脚本来代替手动执行部署过程。对于WCF来说,最好的部署环境是IIS,尤其是包含了WAS的IIS7。最好的IIS上的部署工具是微软即将发布的Web Deployment Tool工具。可以访问其官方网站获得更多详情。

如果使用批处理脚本来自动化部署,那么自动化部署的复杂度就依赖于脚本的复杂度。一个批处理脚本可能包含许多任务,诸如:文件复制、DLL注册、IIS设置、Windows服务设置,甚至更复杂的依赖于其他资源和服务的任务。即使我们用像Web Deployment Tool这样功能强大的部署工具,它也只是能帮你更容易的创建部署脚本,并不会减小实际需要执行的任务的复杂程度。所以说,想要真正简化部署的过程,降低部署成本,我们更应该寻找能够减少或者转移走部署过程中的各种依赖的方法。

配置集中管理对自动化部署的好处

前一章说到了配置集中管理,可能的配置包括服务的元数据、数据库连接字串、应用设置、策略等等。实际上,你很容易就能想象,绝大多数部署过程中可能有的依赖,都和这些配置有关。换句话说,配置管理越集中化,自动化部署也就能变得更简单也更轻巧。

例如。从Dev、QA、Staging到Live环境:

  • 消费和提供服务的元数据因为不同的端点地址、安全和日志策略可能不同。
  • 数据库服务器可能不同,所以,数据库连接字串也可能不同。
  • 任何关联整合的外部资源,诸如:URI,链接,缓存服务器地址等等都可能不同。

如果我们保证大多数配置都能被集中管理,那么在最理想的情况下(实际上,实践中,绝大多数情况下都能达到最理想情况),我们甚至能使得在任意环境部署的文件完全一致,不需要修改。

IIS对简化自动化部署的好处

大多数读者可能已经在IIS里至少部署过最简单的WCF演示程序了,感觉有任何难的吗?想必最可能让人觉得有一点复杂的是元数据(服务行为、端点)的配置。前面讨论过了,如果我们能从应用程序配置文件中移除这个复杂度,你是不是会说他已经足够简单了呢?这是因为IIS还给我们提供了另三个好处:

  • 自动地址绑定。

如果一个WCF服务部署在IIS里,就不需要显式指定服务发布的地址了,因为地址可以通过部署的文件夹和网站的地址和端口计算出来。

  • 自动端口共享。

网站的端口自动地被所有部署在网站中的服务共享。更进一步,在IIS7中,因为IIS7支持诸如TCP这样的更多的接口,部署在IIS7中的服务甚至可以自动共享相同的TCP端口。我们甚至可以在IIS7里让多个不同类型的端点绑定(WSHttp, NetTCP, NetPipedName)指向单一的一个完全相同的服务地址(不包含地址的前缀如’http:’部分)。

  • 自动的服务宿主管理。

在其他的WCF服务宿主环境,诸如命令行程序或Windows服务程序中,必须要写额外的代码来管理ServiceHost类的实例的生命周期;而在IIS中,我么们可以简单的写一个.svc文件,IIS通过.NET Framework提供的ServiceHostFactory类可以自动为你管理ServiceHost实例的生命周期。尽管.NET Framework提供的ServiceHostFact的默认实现只能从应用程序配置文件读取WCF服务的元数据配置,我们可以写一个自定义的ServiceHostFactory类,从其他地方,例如我们提到过的集中化的配置中心读取元数据配置。下面的代码是一个从集中化的Store读取元数据配置的自定义的ServiceHostFactory实现片断:

1      public   class WcfServiceHostFactory : ServiceHostFactory
2      {
3          //
4 
5          protected   override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
6          {
7              var serviceContracts = WcfServiceHelper.GetServiceContracts(serviceType);
8 
9              var host =   new ServiceHost(serviceType, BuildBaseAddresses(serviceContracts));
10              foreach (var serviceContract in serviceContracts)
11              {
12                  var endpoints = EndpointStore.GetServerEndpoints(serviceContract);
13                  if (endpoints.Count ==   0 )
14                      return host;
15 
16                  foreach (var endpoint in endpoints)
17                  {
18                      var address = WcfServiceHelper.BuildAddress(endpoint);
19                      if (address ==   default (Uri)) continue ;
20 
21                      var binding = WcfServiceHelper.BuildBinding(serviceContract, endpoint);
22 
23                      if (binding ==   null ) continue ;
24 
25                      if ( ! IsBehaviorConfigured < ServiceMetadataBehavior > (host))
26                      {
27                          var smb =   new ServiceMetadataBehavior();
28                          host.Description.Behaviors.Add(smb);
29                      }
30 
31                      if (endpoint.MexBindingEnabled)
32                      {
33                          host.AddServiceEndpoint( typeof (IMetadataExchange), new CustomBinding(binding), " mex " );
34                      }
35 
36                      if ( ! IsBehaviorConfigured < ServiceThrottlingBehavior > (host))
37                      {
38                          var serviceThrottle =   new ServiceThrottlingBehavior();
39                          if (endpoint.MaxConcurrentCalls.HasValue)
40                              serviceThrottle.MaxConcurrentCalls = endpoint.MaxConcurrentCalls.Value;
41                          if (endpoint.MaxConcurrentInstances.HasValue)
42                              serviceThrottle.MaxConcurrentInstances = endpoint.MaxConcurrentInstances.Value;
43                          if (endpoint.MaxConcurrentSessions.HasValue)
44                              serviceThrottle.MaxConcurrentSessions = endpoint.MaxConcurrentSessions.Value;
45                          host.Description.Behaviors.Add(serviceThrottle);
46                      }
47 
48                      if ( ! IsBehaviorConfigured < ServiceDebugBehavior > (host) && endpoint.IncludeExceptionDetailInFaults.HasValue && endpoint.IncludeExceptionDetailInFaults.Value)
49                      {
50                          var serviceDebug =   new ServiceDebugBehavior
51                                                 {
52                                                     IncludeExceptionDetailInFaults =
53                                                         endpoint.IncludeExceptionDetailInFaults.Value
54                                                 };
55                          host.Description.Behaviors.Add(serviceDebug);
56                      }
57 
58                      host.AddServiceEndpoint(serviceContract, binding, address);
59                  }
60              }
61 
62              return host;
63          }
64 
65      }
提示
  • 一般,在.svc文件中指定的Type是服务的实现类的类型,ServiceHostFactory的CreateHostHost方法会将这个类型作为参数传给ServiceHost类的构造函数。但是,也可以只在.svc文件里指定服务的接口类型,然后通过使用诸如Unity和Castle这样的IoC容器,在你的自定义ServiceHostFactory的实现中,先从服务接口类型获取服务的实现类型,然后再传给ServiceHost的构造函数。
  • 在自定义的ServiceHostFactory实现中,要小心捕获创建ServiceHost的过程中的错误并记录日志,因为任何在ServiceHost的创建过程中抛出的的异常的详细信息都不会反映给服务的客户端。客户端永远不会知道是为什么,只会收到一个连接被拒绝的消息。不过我们还是可以像调试其他Web应用程序一样,用VS2008的远程调试工具来调试自定义的ServiceHostFactory的。

参考

(1) SOA Design Pattern Catalog: http://www.soapatterns.org/

 

//我是结尾符,待续…

Tag标签: nintegrate soa
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值