总结WCF开发中遇到的几个问题

最近的项目,需要用到WCF,在以前的工作中,经常是将WCF托管在IIS中,主要有几下几个原因:
      第一:部署非常方便,和部署一个站点没什么区别;
      第二:不受防火墙的影响,因为一般服务器上80端口都是开放的;
      第三:IIS托管不需要程序编写托管代码

以前WCF的绑定基本上都是用wsHttpBinding,但这次项目需要将WCF配置成MSMQ,于是我们就需要用到netMsmqBinding,在采用netMsmqBinding过程中遇到如下问题:

第一:netMsmqBinding绑定权限问题。
      原来服务托管在控制台时,服务正常,但托管在windows服务时就会出现如下异常:
      System.TypeInitializationException: “System.ServiceModel.Channels.Msmq”的类型初始值设定项引发异常。 ---> System.ServiceModel.MsmqException: 版本检查失败,错误为:“消息队列服务不可用 (-1072824309, 0xc00e000b)”。无法检测到 MSMQ 的版本。该队列通道上的所有操作都将失败。确保已安装 MSMQ 且 MSMQ 可用。
      这条信息显示没有权限,但控制台是没问题的,原因如下:
      创建消息队列是用登录帐户,而运行控制台程序也是登录帐户,所以没有权限问题,但windows服务在运行时的帐户不一定就是登录帐户,一般我们指定的是ServiceAccount.LocalSystem,于是将消息队列增加everyone权限,问题解决。

另外我将服务托管在IIS7上,总会不成功,不知道大家有没有成功过,如果有成功的,希望给个示例。队列权限为everyone,还加了个匿名用户。

第二:服务端与客户端配置不同导致不能通信,当采用默认生成的配置通信正常,采用程序编码形式编写配置,通信异常,最后发现是binding中的属性exactlyOnce值不同。这种配置主要是指服务端的配置,比如客户端的超时时间等设置就可以任意指定。

NetMsmqBinding result =new NetMsmqBinding(NetMsmqSecurityMode.None);
        result.ExactlyOnce =false;

第三:服务托管方式问题。
      由于本人还未将netMsmqBinding托管在IIS上,所以只能托管在windows服务中,本来托管在控制台也可以,但应用程序的开启比较容易受其它登录用户的影响。这托管成windows服务时遇到如下问题:
      场景:我需要将同一服务程序,部署为N个不同端口不同服务名称的服务。
      问题:当安装一个服务后,正常启动,在安装第二个服务时,第二个服务的执行地址会记成第一个服务的地址。
      分析:有可能是windows服务在安装过程中有安装记录,即使指定了服务程序路径也会受影响,大家有啥好办法就请教。
      解决方案:将服务的exe,config更改名称,例如ComputeAsyncTask_Hight_1.exe,ComputeAsyncTask_Hight_2.exe,ComputeAsyncTask_Hight_3.exe,这种情况下,安装后的执行路径就没有问题。
      遗留问题:虽然上面方案能解决执行路径问题,但在如下情况下依然有问题:
      当所有服务都正常安装后,再次执行安装,比如再次安装ComputeAsyncTask_Hight_1.exe,首先是服务删除,此时系统所识别的assemblypath依然是ComputeAsyncTask_Hight_3.exe,此时就会将ComputeAsyncTask_Hight_3删除,这种情况目前还未找到好的方法。

第四:如何快速彻底删除一个windows服务
      当一个服务安装后,但由于某些BUG做了调整,在某种情况下就会出现无法删除服务的情况,这种问题经常消耗我大量时间去排查,我们可以借用用sc.exe这个Windows命令来解决,效果非常好,再也不用花精力去分析服务为什么不能删除的原因了。
        开始——运行——cmd.exe,使用办法很简单:
        sc delete "服务名"  (如果服务名中间有空格,就需要前后加引号)

第五:在服务的安装类中不能引用app.config
      如果将服务托管为windows服务,一般都会编写服务安装代码,这样我们就可以利用ManagedInstallerClass.InstallHelper来实现服务的自动安装,它主要是用来代替Installutil.exe手工操作。我在项目中需要将同一服务程序部署为不同端口不同服务名称的服务,所以我考虑将服务名称从app.config中指定,于是就是类似下面的代码:

service =new ServiceInstaller();
       service.ServiceName = ConfigurationManager.AppSettings["ServiceName"].Trim();

但在安装过程中总是报错,查明原因,是无法找到配置节,最后才知道当服务在安装时,并不是一个应用程序,理所当然就不会加载app.config,所以在安装类中我们不能调用app.config。
      解决方案:将配置节从app.config中转移,比如新建一个xml文件,然后在安装时,服务名称等信息从xml配置文件中读取。

service.ServiceName = GetComputeLevel();
      privatestring  GetComputeLevel()
        {
            try
            {
                string strPath;
                XmlDocument xmldoc =new XmlDocument();
                XmlNode xmlnd;

strPath = System.Environment.CurrentDirectory [email protected]"\ComputeLevelConfig.xml";
                strPath = AppDomain.CurrentDomain.BaseDirectory [email protected]"\ComputeLevelConfig.xml";
                if (!File.Exists(strPath))
                {
                    thrownew FileNotFoundException("未能找到配置文件"+strPath);
                }
                xmldoc.Load(strPath);
                xmlnd = xmldoc.SelectSingleNode("ComputeLevelConfig");
                if (null!= xmlnd)
                {
                    return xmlnd.InnerText.Trim ();
                }
                else
                {
                    thrownew Exception("没有指定计算优先级!"+ strPath);
                }                
            }
            catch (Exception ex)
            {
                throw ex;
            }           
        }

第六:重新认识WCF服务端配置。
        以前在开发WCF时,大多都是基于默认配置,当一个服务写好之后,以后在开发新的服务,基本都是参考以前成功的案例,所以对服务端的配置文件未做过多了解。借这次机会,重  新整理下服务端配置文件的构造情况。
        主体结构分为以下三个部分:
        1:behaviors
          默认情况会出现如下两个节点,如果想让服务端向客户端抛出详细错误,可以修改includeExceptionDetailInFaults,其它的节点我目前还未使用过。

<serviceMetadata httpGetEnabled="true"/><serviceDebug includeExceptionDetailInFaults="false"/>

2:bindings
         指定绑定模式,我这里指定netMsmqBinding,下面的内容,可以补充一些与默认值不相同的内容,比如exactlyOnce,security,其它不需要额外指定的,就为默认值。

<binding name="msmqBinding" exactlyOnce="false"><security><transport msmqAuthenticationMode="None" msmqProtectionLevel="None"/><message clientCredentialType="None"/></security></binding>

3:services
          最重要的数endpoint以及host,endpoint理解ABC就行:
          A:address,服务地址,如果是wshttpbing这种IIS托管形式,此处应该为空字符串,如果是非http绑定,例如netMsmqBinding,需要指定队列地址;
          B:binding,绑定类型
          C:contract,服务契约
          host这个结点一般是针对非http绑定,用它来提供基地址,http绑定就不需要配置了。

<host><baseAddresses><add baseAddress="http://localhost:8732/Design_Time_Addresses/Cloud.AsyncTaskFramwork.Host/ComputeService/%22/></baseAddresses></host>

理解它的结构,以后在配置各种类型的服务时就能心中有数了。

时间: 2024-07-29 13:59:29

总结WCF开发中遇到的几个问题的相关文章

WCF开发中的Web.config和App.config

WCF uses the System.Configuration configuration system of the .NET Framework. When configuring a service in Visual Studio, use either a Web.config file or an App.config file to specify the settings. The choice of the configuration file name is determ

WCF项目中出现常见错误的解决方法:基础连接已经关闭: 连接被意外关闭

原文:WCF项目中出现常见错误的解决方法:基础连接已经关闭: 连接被意外关闭 在我们开发WCF项目的时候,常常会碰到一些莫名其妙的错误,有时候如果根据它的错误提示信息,一般很难定位到具体的问题所在,而由于WCF服务的特殊性,调试起来也不是那么方便,因此往往会花费不少时间来进行跟踪处理.本文介绍我在我在我的框架里面使用WCF服务的时候,出现的一个常见错误的处理方法,它的提示信息是:基础连接已经关闭: 连接被意外关闭.这种情况我碰到的有两种,一种是返回DataTable的时候出现的,一种是返回实体类

WCF 开发实战系列 (一)

也许有读者会说,为什么要谈 WCF?近期不是 Web API 比较热门?在这个手机.Devices 当道的现在,究竟有什么地方会需要使用到 WCF 呢? 的确,现在访间你能找到的课程,或者您可能参与某项目的实践 (网页应用程序.手机 APP 也好),你需要的通常也都是提供 Services 层,而这个 Services 层通常也就是 Web API.那么,难道 WCF 就无用武之地?其实也不是,看什么情况用什么技术,有一些地方是 Web API 无法做到的 前言 也许有读者会说,为什么要谈 WC

Android实际开发中的首页框架搭建(二、首页框架实现)

本来这一篇是前两天就要写的,奈何事多缠身,推到今日,为自己的拖延感到愧疚... 上一篇大概把项目的结构完成了,下一步就是实现首页切换功能了 首先在activity目录下新建一个HomeActivity,作为承载多个fragment的容器 代码如下 1 /* 2 * * 3 * * ******************************************************* 4 * * 5 * * @文件名称:HomeActivity.java 6 * * @文件作者:ouyan

结构化方法和面向对象方法在软件开发中的对比

学习过C语言和JAVA的同学们一定清楚,这两种语言代表了两种不同的开发方式,即以C语言为代表的结构化开发方法和JAVA代表的面向对象的开发方法.由于二者在程序结构上有着很大的区别,因此,在软件开发领域中,根据自己的需求来选择合理的开发方式就显得尤为重要. 开发软件通常有三个层次: 1.满足用户需求 2.可维护性,即可修改性,让软件能随着用户需求的变更而容易改变 3.可重用性(在其它软件中,能尽量重用该软件的模块) 通过对软件的这三个主要层次的分析,我们就能在实际开发中确定我们的选择. 结构化方法

Java开发中的23种设计模式详解(转)

设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样.项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周

HTML5移动开发中的meta与link

meta HTML5移动开发中的一些webkit专属头部标签,能够帮助浏览器更好的解析HTML代码,从而为HTML5移动开发提供更好的前端表现与体验 viewport网页缩放 1 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" /> UTF-8编码 1

iOS开发中didSelectRowAtIndexPath tap事件响应延迟

为UITableViewCell添加tapped事件,代码如下: class VideoViewController: UIViewController , UITableViewDataSource,UITableViewDelegate { //... func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) { // 播放框背景图片 let imageName : Str

iOS开发中UIPopoverController的使用详解

这篇文章主要介绍了iOS开发中UIPopoverController的使用,代码基于传统的Objective-C,需要的朋友可以参考下 一.简单介绍 1.什么是UIPopoverController 是iPad开发中常见的一种控制器(在iPhone上不允许使用) 跟其他控制器不一样的是,它直接继承自NSObject,并非继承自UIViewController 它只占用部分屏幕空间来呈现信息,而且显示在屏幕的最前面 2.使用步骤 要想显示一个UIPopoverController,需要经过下列步骤