WCF服务器搭建-服务Host篇(ServiceHostGroup实现host)
研究WCF也有一段时间了,开始研究是因为对remoting的一个应用,然后开始了WCF的学习历程,对于Hello World的Demo这里就不记载啦,当我摸索了一段时间之后,发现一个问题一直在困扰着我,就是众所周知可以通过ServiceHost来host一个个的WCF服务实例,然而,当WCF服务的数量比较庞大的时候,应该用那种方式来host服务呢,在《Advanced .Net Remoting》的作者博文中,看到了一个做法,也是我一直想实现的做法,提的要求有两个:
1、多个服务统一部署和管理,方便加减服务。
2、WCF独立配置文件,独立于app.config和web.config配置文件。
做了个简单的例子,大家可以参考参考:
1、通过 configFileMap.ExeConfigFilename 设置独立配置文件目录。
//get custom config file name by our rule: config file name = ServiceType.Name // var myConfigFileName = this.Description.ServiceType.FullName; var myConfigFileName = "WCFSetting"; //get config file path string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase; string myConfigFilePath = System.IO.Path.Combine(dir, myConfigFileName + ".config"); var configFileMap = new System.Configuration.ExeConfigurationFileMap(); configFileMap.ExeConfigFilename = myConfigFilePath; var conf = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFileMap,ConfigurationUserLevel.None); // ServiceModelSectionGroup svcmod = (ServiceModelSectionGroup)conf.GetSectionGroup("system.serviceModel"); var svcmod = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(conf);
2、自定义ServiceHost来实现WCF服务的配置信息从自定义的config中读取。
public class MyServiceHost : ServiceHost { public MyServiceHost(Type t):base(t) { } /// <summary> /// override ApplyConfiguration to load config from custom file /// </summary> protected override void ApplyConfiguration() { //get custom config file name by our rule: config file name = ServiceType.Name // var myConfigFileName = this.Description.ServiceType.FullName; var myConfigFileName = "WCFSetting"; //get config file path string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase; string myConfigFilePath = System.IO.Path.Combine(dir, myConfigFileName + ".config"); if (!System.IO.File.Exists(myConfigFilePath)) { base.ApplyConfiguration(); return; } var configFileMap = new System.Configuration.ExeConfigurationFileMap(); configFileMap.ExeConfigFilename = myConfigFilePath; var config = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None); var serviceModel = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(config); if (serviceModel == null) { base.ApplyConfiguration(); return; } foreach (ServiceElement serviceElement in serviceModel.Services.Services) { if (serviceElement.Name == this.Description.ServiceType.FullName) { LoadConfigurationSection(serviceElement); return; } } throw new Exception("there is no service element match the description!"); } }
3、通过static List<ServiceHost>来实现多服务统一管理:
public class ServiceHostGroup
{
static List<ServiceHost> _hosts = new List<ServiceHost>();
/// <summary>
/// open and host servcie.
/// </summary>
/// <param name="t"></param>
private static void OpenHost(Type t)
{
try
{
MyServiceHost hst = new MyServiceHost(t);
Type ty = hst.Description.ServiceType;//ty
hst.Open();
_hosts.Add(hst);
}
catch (Exception ex)
{
throw;
}
}
public static void StartAllConfiguredServices()
{
//get custom config file name by our rule: config file name = ServiceType.Name
// var myConfigFileName = this.Description.ServiceType.FullName;
var myConfigFileName = "WCFSetting";
//get config file path
string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
string myConfigFilePath = System.IO.Path.Combine(dir, myConfigFileName + ".config");
var configFileMap = new System.Configuration.ExeConfigurationFileMap();
configFileMap.ExeConfigFilename = myConfigFilePath;
var conf = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
// ServiceModelSectionGroup svcmod = (ServiceModelSectionGroup)conf.GetSectionGroup("system.serviceModel");
var svcmod = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(conf);
foreach (ServiceElement el in svcmod.Services.Services) {
string Namespace = el.Name.Substring(0, el.Name.LastIndexOf("."));
Type svcType = Type.GetType(el.Name + "," + Namespace);
if (svcType == null) throw new Exception("Invalid Service Type " + el.Name + " in configuration file.");
OpenHost(svcType);
}
}
public static void CloseAllServices()
{
foreach (ServiceHost hst in _hosts)
{
hst.Close();
}
}
}
4、配置文件WCFSetting.config如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WcfServerBehavior">
<!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点-->
<serviceMetadata/>
<!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息-->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="BusContractService.BuyFruitService" behaviorConfiguration="WcfServerBehavior">
<endpoint binding="netTcpBinding" contract="IBusContract.IBuyFruit" bindingConfiguration="ServerBinding" address=""/>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:3287/MeiyaWcf/IBuyFruit"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<!--安全http-->
<wsHttpBinding>
<binding name="NoneSecurity" maxBufferPoolSize="12000000" maxReceivedMessageSize="12000000" useDefaultWebProxy="false">
<readerQuotas maxStringContentLength="12000000" maxArrayLength="12000000"/>
<security mode="None"/>
</binding>
</wsHttpBinding>
<!--Tcp-->
<netTcpBinding>
<binding name="ServerBinding">
<security mode="None">
<transport clientCredentialType="None"/>
<message clientCredentialType="None"/>
</security>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
</configuration>
5、在相应的应用程序载体加入代码段:
ServiceHostGroup.StartAllConfiguredServices();
至于WCF服务端实例代码就不贴啦,这样做的好处,多个WCF统一管理,WCF配置文件独立,方便管理。当然,代码还有很多需要优化的,等总结的篇章再给个完善点的方案吧。
posted on 2012-03-08 15:18 wu-yansheng 阅读(857) 评论(0) 编辑 收藏 举报