none
WCF如何实现不同Service相互访问? RRS feed

  • 问题

  • 大家好,刚刚接触WCF不久,有一些问题,但又不得解,在此向大家请教。

    1. 假如以下使用场景:

    位于不同Host不同PC的Service1(S1)和Service2(S2)
    S1提供Function1(F1)和Function2(F2);
    S2提供Function3(F3)和Function4(F4,非OperationContract标记);

    交代完了,开始绕口令:S2的F4调用S1的F1;S1的F2调用S2的F3。

    我尝试了在S2中引用S1,将S2作为S1的客户端来操作。这样后,生成的配置文件有点混乱,非常复杂,而且目前调试还没有通过。不知道还有没有其它的途径实现上述需求?

    2. WinForm调用WCF无响应问题

    一个简单的HelloWCF,Service提供SayHello(string userName),输出“Hello, XXX.”,客户端是Console Application时,非常快的就得到执行结果;当建立Windows Application来调用Service时,第一次调用接口时,总是要无响应一会(目测2秒左右)才能正常运行,之后再重复调用都是立刻就成功。不知道是什么原因导致WinApp第一次调用WCF时的停顿?有无解决方法?

    以上问题,困惑了很久。

    • 已编辑 Wolf Lai 2011年6月1日 8:46 内容不完整。
    2011年6月1日 8:46

答案

  • 嗯,调用能够成功。

    Sorry,当初偶然发现该问题时,就编写了以上代码。但是,看过Peter提供的文章后,再核对代码,有Risk存在,修改后代码如下:

    private void button1_Click(object sender, EventArgs e)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        using (Service1Client proxy = new Service1Client())
        {
            sw.Stop();
            Console.WriteLine("Create proxy cost {0} ms.", sw.ElapsedMilliseconds);
            sw.Reset();
            sw.Start();
            proxy.Open();
            sw.Stop();
            Console.WriteLine("proxy.Open() cost {0} ms.", sw.ElapsedMilliseconds);
            sw.Reset();
            sw.Start();
            proxy.DoWork("XYZ");
            sw.Stop();
            Console.WriteLine("proxy.DoWork(...) cost {0} ms.", sw.ElapsedMilliseconds);
        }
    }

     

    多次记录首次请求运行结果为:

    Create proxy cost 592 ms.
    proxy.Open() cost 102 ms.
    proxy.DoWork(...) cost 20 ms.
    Create proxy cost 112 ms.
    proxy.Open() cost 86 ms.
    proxy.DoWork(...) cost 14 ms.
    Create proxy cost 71 ms.
    proxy.Open() cost 42 ms.
    proxy.DoWork(...) cost 16 ms.

     

    呵呵,结果是自己编码问题。 经多次测试后发现,加上using语句后,耗时明显减少(未添加时第一次Create耗时大概500ms,Open耗时大概1000ms)。

    数据最有说服力啊。偶然一次出现稍微耗时的情况,能够接受了。其中有网络带来的几率?可能。


    QQ: 79965521 Email: WolfLai@126.com

     



    2011年6月7日 12:40

全部回复

  • 1.

    没通过,错误是什么?如果S1去调用S2,那么S1就是作为客户端来调用S2.

    你要是使用了配置文件,那么S1里一定要有对应的配置节点,这些是调用S2必须的。

    2.你测试的Window程序是什么?win form程序?那调用的代码有吗?

    另外测试的时候服务是不是 独立 托管的?

    Winform 调用 Winform 自己托管的 服务 会出现线程交互的问题

     


    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
     

    老徐的网站】:http://www.frankxulei.com/

    微软WCF中文技术论坛
    微软WCF英文技术论坛

    Windows Azure中文技术论坛

    2011年6月2日 3:36
    版主
  • Hi, Frank, 谢谢你的回复。

    1. 没通过的错误是EndPointException(名字记不太清楚了),我确认没有配置错。因为当初单独调试时,S1和S2都能被调用成功;

    2. Windows程序就是普通的WindowsApplication工程,调用过程就是简单的创建对应Client的proxy,然后调用OperationContract。在ConsoleApplication里面非常正常,毫无瑕疵的就能瞬间得到运行结果;

    3. 测试的时候,服务是独立托管,寄宿在单独的ConsoleApplication里面;

    4. 代码在家,是自己写的练习程序,晚上回家后再邮件发送给你。

    再次感谢回复。

    2011年6月2日 5:58
  • 对于MS论坛,使用起来发现一个问题:交互起来太耗时间了,一问一答的周期大概是一天。提问和解答都在北京时间,没有时差问题,就是因为被回复后不能及时的知道,所以交互的响应就被增加。除了MSN外,如果添加一个即时提醒功能,或许交互起来更快捷有效。

    提个建议,在提问和回复后,如果大家能附上有效的即时联系方式(QQ或Email),那就很完美了。MS论坛集中了很多技术精英,很多问题都不是非常巨大的非常难处理的问题。就仅仅是一个思路上的弯弯,如果转过那个弯弯,都能够迎刃而解。但由于对技术的熟练程度上,导致了很多弯弯的存在,需要走在前面的兄台站出来指点迷津,引导一下迷茫中的人。

    当然,以上都是以一个求助者的角度提议,总之都是希望像我一样的朋友能够尽快提升,接近MVPs的层次。

    2011年6月2日 6:57
  • 1尽量使用 向导生成的配置文件。确保自己的做的修改正确

    2.如果单独更换客户端程序 只要配置正确 不影响调用结果

    3.这个独立托管应该不受影响

    4.可以贴出来一下~

     

     


    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
     

    老徐的网站】:http://www.frankxulei.com/

    微软WCF中文技术论坛
    微软WCF英文技术论坛

    Windows Azure中文技术论坛

    2011年6月2日 12:12
    版主
  • 对于MS论坛,使用起来发现一个问题:交互起来太耗时间了,一问一答的周期大概是一天。提问和解答都在北京时间,没有时差问题,就是因为被回复后不能及时的知道,所以交互的响应就被增加。除了MSN外,如果添加一个即时提醒功能,或许交互起来更快捷有效。

    提个建议,在提问和回复后,如果大家能附上有效的即时联系方式(QQ或Email),那就很完美了。MS论坛集中了很多技术精英,很多问题都不是非常巨大的非常难处理的问题。就仅仅是一个思路上的弯弯,如果转过那个弯弯,都能够迎刃而解。但由于对技术的熟练程度上,导致了很多弯弯的存在,需要走在前面的兄台站出来指点迷津,引导一下迷茫中的人。

    当然,以上都是以一个求助者的角度提议,总之都是希望像我一样的朋友能够尽快提升,接近MVPs的层次。


    帖子里有个 “警报” 实际 就是邮件 提醒 功能。

    这里翻译 的很傻,应该是 提醒


    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
     

    老徐的网站】:http://www.frankxulei.com/

    微软WCF中文技术论坛
    微软WCF英文技术论坛

    Windows Azure中文技术论坛

    2011年6月2日 12:13
    版主
  • 郁闷。老婆出差把本本带去看《回家的诱惑》了。。。

    先看Windows程序第一次访问WCF时会无响应几秒的问题吧。

    目录结构如下:

    Hello.sln

    -- Host.csproj

        -- IService1.cs

        -- Service1.cs

        -- Program.cs

        -- App.config

    --ClientConsole.csproj

        -- app.config

        -- Program.cs

    --ClientWindows.csproj

        -- app.config

        -- Form1.cs

        -- Program.cs

    源码片段如下:

    IService1.cs

     // 注意: 如果更改此处的接口名称 "IService1",也必须更新 App.config 中对 "IService1" 的引用。
    
     [ServiceContract]
    
     public interface IService1
    
     {
    
      [OperationContract]
    
      void DoWork(string userName);
    
     }
    
    

    Service1.cs

     // 注意: 如果更改此处的类名 "Service1",也必须更新 App.config 中对 "Service1" 的引用。
    
     public class Service1 : IService1
    
     {
    
      public void DoWork(string userName)
    
      {
    
       Console.WriteLine("Hello, {0}", userName);
    
      }
    
     }
    
    

    Program.cs

    namespace Host
    
    {
    
     class Program
    
     {
    
      static void Main(string[] args)
    
      {
    
       using (ServiceHost host = new ServiceHost(typeof(Service1)))
    
       {
    
        host.Open();
    
        Console.ReadLine();
    
        host.Close();
    
       }
    
      }
    
     }
    
    }

    ClientConsole.csproj

    namespace ClientConsole
    
    {
    
     class Program
    
     {
    
      static void Main(string[] args)
    
      {
    
       Service1Client proxy = new Service1Client();
    
       proxy.DoWork("XYZ");
    
    
    
       Console.ReadLine();
    
      }
    
     }
    
    }
    
    

    ClientWindows.csproj

    namespace ClientWindows
    
    {
    
     public partial class Form1 : Form
    
     {
    
      public Form1()
    
      {
    
       InitializeComponent();
    
      }
    
    
    
      private void button1_Click(object sender, EventArgs e)
    
      {
    
       Service1Client proxy = new Service1Client();
    
       proxy.DoWork("XYZ");
    
      }
    
     }
    
    }

    服务端配置:

    <?xml version="1.0" encoding="utf-8" ?>
    
    <configuration>
    
     <system.serviceModel>
    
      <behaviors>
    
       <serviceBehaviors>
    
        <behavior name="Host.Service1Behavior">
    
         <serviceMetadata httpGetEnabled="true" />
    
         <serviceDebug includeExceptionDetailInFaults="false" />
    
        </behavior>
    
       </serviceBehaviors>
    
      </behaviors>
    
      <services>
    
       <service behaviorConfiguration="Host.Service1Behavior" name="Host.Service1">
    
        <endpoint address="" binding="wsHttpBinding" contract="Host.IService1">
    
         <identity>
    
          <dns value="localhost" />
    
         </identity>
    
        </endpoint>
    
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    
        <host>
    
         <baseAddresses>
    
          <add baseAddress="http://localhost:8731/Service1/" />
    
         </baseAddresses>
    
        </host>
    
       </service>
    
      </services>
    
     </system.serviceModel>
    
    </configuration>
    
    
    
    

    客户端配置:

    <?xml version="1.0" encoding="utf-8" ?>
    
    <configuration>
    
     <system.serviceModel>
    
      <bindings>
    
       <wsHttpBinding>
    
        <binding name="WSHttpBinding_IService1" closeTimeout="00:01:00"
    
         openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
    
         bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
    
         maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
    
         messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
    
         allowCookies="false">
    
         <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
    
          maxBytesPerRead="4096" maxNameTableCharCount="16384" />
    
         <reliableSession ordered="true" inactivityTimeout="00:10:00"
    
          enabled="false" />
    
         <security mode="Message">
    
          <transport clientCredentialType="Windows" proxyCredentialType="None"
    
           realm="" />
    
          <message clientCredentialType="Windows" negotiateServiceCredential="true"
    
           algorithmSuite="Default" establishSecurityContext="true" />
    
         </security>
    
        </binding>
    
       </wsHttpBinding>
    
      </bindings>
    
      <client>
    
       <endpoint address="http://localhost:8731/Service1/" binding="wsHttpBinding"
    
        bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
    
        name="WSHttpBinding_IService1">
    
        <identity>
    
         <dns value="localhost" />
    
        </identity>
    
       </endpoint>
    
      </client>
    
     </system.serviceModel>
    
    </configuration>

    好,基本贴完了。

    再简单描述一下:

    1. Service提供方法:DoWork(string userName);接收传入参数,打印到控制台;

    2. ConsoleClient,连接到Service,传入xyz;

    3. ConsoleWindows,在Form1中,添加按钮button1,在点击事件里处理:连接到Service,传入xyz。

    4. 运行后发现,ConsoleClient调用DoWork后,立马就能在控制台输出结果;ConsoleWindows中,第一次点击button1会无响应2-3s,之后再次点击无论多少次,都是即刻就能响应操作。

    Frank,如过可以,我能否将源码发送到你的邮箱里面。


    QQ: 79965521 Email: WolfLai@126.com
    • 已编辑 Wolf Lai 2011年6月2日 13:19 重新排版。
    2011年6月2日 13:16
  • Hi, guys, 不知道我遇到的问题是不是问题?或许各位没有遇到过?还是我的配置或者编码有误?或者其它什么原因导致? 请不吝赐教。
    QQ: 79965521 Email: WolfLai@126.com
    2011年6月7日 7:25
  • Hi,

    你可以参考下面这个英文链接,里面涉及到了哪几个方面会导致第一次调用WCF service会比较慢,而且提供了解决方法。

     #WCF First Call Slow

     http://www.codeproject.com/Tips/114132/WCF-First-Call-Slow.aspx


    Please mark the replies as answers if they help or unmark if not. If you have any feedback about my replies, please contact msdnmg@microsoft.com Microsoft One Code Framework
    2011年6月7日 7:46
    版主
  • Hi,Peter,谢谢你提供的链接,晚上回家再试试。

    看过后,还是有一些疑问:

    1. 我的Service是寄宿在Console Application中的,还是会有其中提及的访问时编译、自动停止问题么?

    2. 如果真是这样,为什么用Console Application的客户端访问时,非常流畅的就能调用成功?

    仔细想想后,我怀疑是以下原因导致第一次访问无响应现象,不妥之处,请指正:

    Windows Application和WCF服务之间通讯,首先要建立一个连接,类似数据库访问的连接。然后客户端再通过该连接使用Service提供的各种契约。

    启动客户端后,屡次发送请求,仅只有第一次会出现无响应。是不是因为第一次请求时该连接不存在,建立连接导致客户端短暂的无响应现象?如果真是这个原因,那还好办,起个线程客户端一启动就后胎请求一次某某契约就行了。

    盼复,谢谢。


    QQ: 79965521 Email: WolfLai@126.com
    2011年6月7日 8:19
  • 你有没有调试你的客户端程序,看看 第一次点击 button 时 proxy.DoWork("XYZ"); 执行时是抛异常了,还是别的什么?
    2011年6月7日 8:25
  • 绝对有调试过。第一次点击Button时,没有任何异常,就是卡在那里几秒才反应出结果。之后就非常快的就执行通过了。
    QQ: 79965521 Email: WolfLai@126.com
    2011年6月7日 8:59
  • 绝对有调试过。第一次点击Button时,没有任何异常,就是卡在那里几秒才反应出结果。之后就非常快的就执行通过了。
    QQ: 79965521 Email: WolfLai@126.com


    也就是说第一次点击后,它能调用成功,是吗?

    如果是这样的话,你可以修改下代码如下:

    proxy.Open();    // 先打开通道

     proxy.DoWork(....);

     


    看一下到底是在哪步调用慢。
    2011年6月7日 9:09
  • 嗯,调用能够成功。

    Sorry,当初偶然发现该问题时,就编写了以上代码。但是,看过Peter提供的文章后,再核对代码,有Risk存在,修改后代码如下:

    private void button1_Click(object sender, EventArgs e)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        using (Service1Client proxy = new Service1Client())
        {
            sw.Stop();
            Console.WriteLine("Create proxy cost {0} ms.", sw.ElapsedMilliseconds);
            sw.Reset();
            sw.Start();
            proxy.Open();
            sw.Stop();
            Console.WriteLine("proxy.Open() cost {0} ms.", sw.ElapsedMilliseconds);
            sw.Reset();
            sw.Start();
            proxy.DoWork("XYZ");
            sw.Stop();
            Console.WriteLine("proxy.DoWork(...) cost {0} ms.", sw.ElapsedMilliseconds);
        }
    }

     

    多次记录首次请求运行结果为:

    Create proxy cost 592 ms.
    proxy.Open() cost 102 ms.
    proxy.DoWork(...) cost 20 ms.
    Create proxy cost 112 ms.
    proxy.Open() cost 86 ms.
    proxy.DoWork(...) cost 14 ms.
    Create proxy cost 71 ms.
    proxy.Open() cost 42 ms.
    proxy.DoWork(...) cost 16 ms.

     

    呵呵,结果是自己编码问题。 经多次测试后发现,加上using语句后,耗时明显减少(未添加时第一次Create耗时大概500ms,Open耗时大概1000ms)。

    数据最有说服力啊。偶然一次出现稍微耗时的情况,能够接受了。其中有网络带来的几率?可能。


    QQ: 79965521 Email: WolfLai@126.com

     



    2011年6月7日 12:40