zoukankan      html  css  js  c++  java
  • WCF开发日志 WCF启动多个服务

    一、摘要

    场景:  

          项目比较大,不可能所有契约在一个类里来实现,可能会有上百个服务上千个契约,按照目前在网上搜索的结果是…..只能一个servicehost对应一个服务,某个mvp的建议是所有契约都放到一个类里来实现。。。我崩溃  。。。。。

    想法:

           也有人建议用 partial class的方式,把不同的契约分布到不同的CS文件里,虽然可能看上去好一点,但每回添加服务都得重编译,我觉得太扯淡了 。。。。。

           我希望是尽可能的把服务根据功能的不同按模块划分开来,不同的服务做成不同的dll,以插件的形式注册到一个表里,用servicehost来加载,不知大家有没有好的建议 。

           其实可以考虑用CSLA.NET的方案,只写一个服务,它称为统一入口,这个方式还是不错的,就是他为解决并发,并发好像在博客园里有人写了怎么实现,地址是                  http://www.cnblogs.com/zgynhqf/archive/2010/07/01/1769228.html

    现实: 

    说一千道一万架不住我不会,我只能实现:

    1、如何在Windows中Host多个WCF服务?
    2、不能是多个Open方法,那样太幼稚了 !

    3、 考虑到整个团队都不会CSLA.NET,或OEA 就我会一点:) , 这个还的多谢周哥,和 胡总 的栽培了。

    4、 整个团队学习成本太高,只有不断的分享,讨论来加快进度了。 
    二、本文大纲

           a、摘要 。

           b、本文大纲 。

           c、项目准备阶段 。

           d、主要核心代码 。

           e、达到的效果图 。

    三、项目准备阶段

    这个图需要一点C# 基础才能看的懂的:) 估计一上图大家就看的懂(自己想象中……..)了。

    clipboard

       这里主要是创建 Windows项目和 WCF Service Library 项目

      Windows项目还需要引用WCF Service Library 项目

    四、主要核心代码

    clipboard[9]

    运行按钮事件代码:

     1:         private void button1_Click(object sender, EventArgs e)
     2:         {
     3:             if (button1.Tag == "run")
     4:             {
     5:                 ServiceStart();
     6:                 button1.Text = "停止(&X)";
     7:                 button1.Tag = "stop";
     8:             }
     9:             else
    10:             {
    11:                 button1.Text = "运行(&R)";
    12:                 button1.Tag = "run";
    13:             }
    14:         }
    15:   

    ServiceStart() 函数代码:

     1:  private List<ServiceHost> serviceHosts = new List<ServiceHost>();
     2:    private void ServiceStart()
     3:    {
     4:   
     5:        #region 初?始?化ˉ serviceHosts
     6:        if (serviceHosts != null)
     7:        {
     8:            foreach (ServiceHost t in serviceHosts)
     9:            {
    10:                if (t != null)
    11:                    t.Close();
    12:            }
    13:        }
    14:        else
    15:        {
    16:            serviceHosts = new List<ServiceHost>();
    17:        }
    18:        #endregion
    19:  
    20:        string serviceAddress = string.Format("net.tcp://{0}:{1}", "127.0.0.1", "8000");
    21:   
    22:        Dictionary<Type,Type> sevtypes=new Dictionary<Type,Type>();
    23:        sevtypes.Add(typeof(IService1),typeof(Service1));
    24:        sevtypes.Add(typeof(IService2), typeof(Service2));
    25:   
    26:        string endpointAddress = string.Empty;
    27:        string tName = string.Empty;
    28:        StringBuilder msgService = new StringBuilder();
    29:        foreach (var item in sevtypes)
    30:        {
    31:            tName = item.Key.Name.Substring(1);
    32:            endpointAddress = serviceAddress + tName;
    33:            if (!serviceAddress.EndsWith("/"))
    34:                endpointAddress = string.Format("{0}/{1}", serviceAddress, tName);
    35:            ServiceHost serviceHost = new ServiceHost(item.Value, new Uri(endpointAddress));
    36:   
    37:            //加载元数据结点
    38:            ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    39:            serviceHost.Description.Behaviors.Add(smb);
    40:            serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
    41:            //加载NetTcpBinding结点
    42:            NetTcpBinding netTcpBinding = new NetTcpBinding();
    43:            netTcpBinding.Security.Mode = SecurityMode.None;
    44:            netTcpBinding.ReceiveTimeout = TimeSpan.Parse("00:10:00");
    45:            netTcpBinding.MaxBufferPoolSize = 2147483647;
    46:            netTcpBinding.MaxBufferSize = 2147483647;
    47:            netTcpBinding.MaxConnections = 10;
    48:   
    49:            netTcpBinding.ReaderQuotas.MaxDepth = 2147483647;
    50:            netTcpBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
    51:            netTcpBinding.ReaderQuotas.MaxArrayLength = 2147483647;
    52:            netTcpBinding.ReaderQuotas.MaxBytesPerRead = 2147483647;
    53:            netTcpBinding.ReaderQuotas.MaxNameTableCharCount = 2147483647;
    54:            netTcpBinding.MaxReceivedMessageSize = 2147483647;
    55:            serviceHost.AddServiceEndpoint(item.Key, netTcpBinding, endpointAddress);
    56:   
    57:            serviceHost.Opened += delegate
    58:            {
    59:                msgService.AppendLine(string.Format("{0}开始监听 Uri 为 :{1}/mex", tName, endpointAddress.ToString()));
    60:            };
    61:   
    62:            serviceHost.Open();
    63:            serviceHosts.Add(serviceHost);
    64:        }
    65:        this.textBox1.Text = msgService.ToString();
    66:    }
    67:   

    代码约定:

        每次增加服务和契约的时候都需要同时添加 Dictionary 要不然系统不会启动新增加的服务。

    服务地址:

    net.tcp://127.0.0.1:8000/服务名/mex

    image

    上面的例子生成如下地址:

    net.tcp://127.0.0.1:8000/Service1/mex

    net.tcp://127.0.0.1:8000/Service2/mex

    把 ”Dictionary ”改成配置文件形式,也就通用了。

    网上的一个使用配置文件的例子:

    配置文件如下:

     1:   <system.serviceModel>
     2:      <services>
     3:        <service name="ChinaQueue.Restaurant.WCFService.ServiceImplementations.PrinterSer" behaviorConfiguration="sb">
     4:          <host>
     5:            <baseAddresses>
     6:              <add baseAddress="net.tcp://localhost:8081" />
     7:            </baseAddresses>
     8:          </host>
     9:          <endpoint name="NetTcpBinding_IPrinterServer" address="PrinterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IPrinterSer" />
    10:          <endpoint name="MexTcpBinding_IPrinterServer" address="Printer" binding="mexTcpBinding" contract="IMetadataExchange" />
    11:        </service>
    12:        <service name="ChinaQueue.Restaurant.WCFService.ServiceImplementations.CounterSer" behaviorConfiguration="sb">
    13:          <host>
    14:            <baseAddresses>
    15:              <add baseAddress="net.tcp://localhost:8081" />
    16:            </baseAddresses>
    17:          </host>
    18:          <endpoint name="NetTcpBinding_ICounterServer" address="CounterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.ICounterSer" />
    19:          <endpoint name="MexTcpBinding_ICounterServer" address="Counter" binding="mexTcpBinding" contract="IMetadataExchange" />
    20:        </service>
    21:        <service name="ChinaQueue.Restaurant.WCFService.ServiceImplementations.QuerySer" behaviorConfiguration="sb">
    22:          <host>
    23:            <baseAddresses>
    24:              <add baseAddress="net.tcp://localhost:8081" />
    25:            </baseAddresses>
    26:          </host>
    27:          <endpoint name="NetTcpBinding_IQueryServer" address="QuerySer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IQuerySer" />
    28:          <endpoint name="MexTcpBinding_IQueryServer" address="Query" binding="mexTcpBinding" contract="IMetadataExchange" />
    29:        </service>
    30:      </services>
    31:      <behaviors>
    32:        <serviceBehaviors>
    33:          <behavior name="sb">
    34:            <serviceMetadata />
    35:            <serviceDebug includeExceptionDetailInFaults="true" />
    36:          </behavior>
    37:        </serviceBehaviors>
    38:      </behaviors>
    39:      <bindings>
    40:        <netTcpBinding>
    41:          <binding name="NetTcpBinding_IServer">
    42:            <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
    43:            <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
    44:            <security mode="None">
    45:              <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
    46:              <message clientCredentialType="Windows" />
    47:            </security>
    48:          </binding>
    49:        </netTcpBinding>
    50:      </bindings>
    51:      <client>
    52:        <endpoint address="net.tcp://localhost:8081/PrinterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IPrinterSer" name="NetTcpBinding_IPrinterServer" />
    53:        <endpoint address="net.tcp://localhost:8081/CounterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.ICounterSer" name="NetTcpBinding_ICounterServer" />
    54:        <endpoint address="net.tcp://localhost:8081/QuerySer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IQuerySer" name="NetTcpBinding_IQueryServer" />
    55:      </client>
    56:    </system.serviceModel>
    57:  

    以上是三个服务的配置,
    然后在Main方法中Host这三个服务,以下是如何从配置文件中读取服务并进行Host的

    System.ServiceModel.Configuration

     1:  Configuration conf = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);
     2:             ServiceModelSectionGroup svcmod = (ServiceModelSectionGroup)conf.GetSectionGroup("system.serviceModel");
     3:             foreach (ServiceElement el in svcmod.Services.Services)
     4:             {
     5:                 Type svcType = Type.GetType(el.Name + "," + "ChinaQueue.Restaurant.WCFService");
     6:                 if (svcType == null)
     7:                     throw new Exception("Invalid Service Type " + el.Name + " in configuration file.");
     8:                 ServiceHost aServiceHost = new ServiceHost(svcType);
     9:                 aServiceHost.Open();
    10:             }
    11:   
    五、达到的效果图

    测试通过,有图作证:

    clipboard[11]

    这个服务启动成功了,客服端也测试通过,耶搞定。  

     

  • 相关阅读:
    html调用php
    MySQL安装下载
    MySQL默认安装下载
    MySQL安装下载
    搭建php环境
    面试官:聊聊对Vue.js框架的理解
    TCP、UDP、HTTP、SOCKET之间的区别与联系
    HTTP/1、HTTP/2、HTTP/3
    git教程
    从jQuery到Serverless,前端十四年挖了多少坑?
  • 原文地址:https://www.cnblogs.com/luomingui/p/2674220.html
Copyright © 2011-2022 走看看