【问题标题】:Parallel WCF calls to multiple servers对多个服务器的并行 WCF 调用
【发布时间】:2010-04-01 19:39:53
【问题描述】:

我有一个 WCF 服务(同一个)在多台服务器上运行,我想从一个客户端并行调用所有实例。我正在使用 ChannelFactory 和接口(合同)来调用服务。每个服务都有一个在 .config 文件中定义的本地 <endpoint> 客户端。

我正在尝试构建某种通用框架以避免代码重复。

例如,单线程中的同步调用如下所示:

    Dim remoteName As String = "endpointName1"
    Dim svcProxy As ChannelFactory(Of IMyService) = New ChannelFactory(Of IMyService)(remoteName)
    Try
        svcProxy.Open()
        Dim svc As IMyService = svcProxy.CreateChannel()
        nodeResult = svc.TestRemote("foo")
    Finally
        svcProxy.Close()
    End Try

我遇到困难的部分是如何指定并实际调用实际的远程方法(例如“TestRemote”),而不必为每个方法复制上述代码以及调用该代码的所有线程相关内容.

最后,我希望能够按照以下方式编写代码(考虑这个伪代码):

Dim results as Dictionary(Of Node, ExpectedReturnType) 
results = ParallelInvoke(IMyService.SomeMethod, parameter1, parameter2) 

其中 ParallelInvoke() 将方法和参数(paramArray 或 object() .. 不管)作为参数,然后在每个远程节点上运行请求,阻塞直到它们都返回答案或超时,然后将结果返回到 Dictionary 中,键为节点,值作为它返回的任何值。

然后我可以(取决于方法)挑选出我需要的单个值,或者将每个服务器的所有值聚合在一起,等等。

我很确定我可以使用反射和 InvokeMember() 来做到这一点,但这需要将方法作为字符串传递(这可能会导致错误,例如调用在编译时无法捕获的不存在的方法),所以我想看看是否有更清洁的方法来做到这一点。

谢谢

【问题讨论】:

  • 不确定您到底想做什么,但您可以检查 WCF 的 svcutil 生成的客户端代理,您将了解如何在较低级别编程以调用传递名称的服务,例如“远程测试”。如果您想明确避免,那么使用反射将起作用,并且不需要传递文字字符串。您可以询问客户端代理以查看哪些方法可用并以这种方式调用它们。

标签: .net wcf reflection parallel-processing


【解决方案1】:
 public static TResult MakeCall<TService, TResult>(Func<TService, TResult> method,  string remoteName)
        {
            // try not to create the factory object for each call, it can be a singleton
            var factory = GetFactory<TService>(remoteName);
            TService proxy = default(TService);
            TResult result = default(TResult);
            try
            {
                proxy = factory.CreateChannel();
                result = method(proxy);
            }
            finally
            {
                // proxy disposal is a bit tricky in WCF and you might need to read more about Close/Abort
                 Close(proxy);                    

            }
            return result;
        }

它允许您在任何接口上调用任何方法,而无需复制管道代码。

public interface IMyService
        {
            int Sum(int a, int b);
            int Max(int a, int b);
        }

公共接口IMyService2 { 布尔测试(字符串值); }

   static void Main(string[] args)
        {
            var a = 12;
            var b = 12;
            var r1 = MakeCall((IMyService proxy) => proxy.Sum(a, b),  "endpoint1");
            var a1 = 12;
            var b1 = 14;
            var r2 = MakeCall((IMyService proxy) => proxy.Max(a1, b1), "endpoint1");
            var r3 = MakeCall((IMyService2 proxy) => proxy.Test("test"), "endpoint2");
        }

您可以使用 MakeCall 作为最终解决方案的构建块。

【讨论】:

    【解决方案2】:

    一种方法是使用:

    System.Threading.ThreadPool.QueueUserWorkItem( ... )

    在这里查看 VB 语法: http://msdn.microsoft.com/en-us/library/4yd16hza.aspx

    将aysnc代码放入WaitCallback中。

    【讨论】:

    • 这将在我上面的示例中的 ParallelInvoke() 方法内部——但仍然无助于选择哪种方法(例如,TestRemote()),而不必复制所有周围的代码每种方法。
    • 是的,你是对的,我没有回答你所有的问题。有关实际答案,请参阅上面 Cheeso 的评论。
    猜你喜欢
    • 2015-09-11
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多