0

多年来,我一直使用 stackoverflow.com 作为专业程序员的资源。当我在谷歌上搜索某些东西时,我会说十分之八,我会在这里找到一个问题和答案,当这种情况发生时我总是会松一口气,因为我知道我即将找到我需要的信息。

我一直在努力解决(我认为是)一个简单的问题,涉及使用 WCF 技术设置路由服务。我在这里浏览了具有类似标题的问题,并且查阅了很多资源(关于该主题的实际书籍以及网站)试图弄清楚这一点,但无济于事。

简而言之,我想设置一个具有以下布局的系统:

{client}<-basicHTTP->{portal/router}<-fullWCF-WS*->{end-point-services1..n}

客户端:获取对门户的服务引用,能够调用端点服务
门户/路由器的功能:从客户端获取请求,并将它们发送到多播设置中
的端点服务 end-point-services1..n:从客户端获取请求,通过门户路由,处理请求以搜索事物,然后响应或将数据记录到数据库中以供稍后检查

我 100% 能够启动并运行路由服务。我能够遵循的最成功的模型在“WCF4 中的新增功能:练习 8 和 9,内容桥接和路由”(msdn.microsoft.com/en-us/gg465212) 和“Hello World with the路由服务”(msdn.microsoft.com/en-us/library/dd795218.aspx)但我使用了我咨询过的所有来源(如下所列)中的点点滴滴。

基本上,让我感到沮丧的是,我希望客户端(第 3 方)能够将 Web 服务引用添加到门户服务(或者,最坏的情况下,使用 svcutil.exe 方法),然后完成通过他们的设置。通过该引用,他们将引用他们想要在所有场景中调用的所有函数/方法。我看过的模型需要 2 个引用,一个指向实际服务,一个指向路由器,然后强制客户端在其设置中专门调用路由器。我使这个特定设置工作的其他尝试都没有奏效。

您对此的帮助将不胜感激。


这是我的工作模型的简化版本,几乎可以满足我的要求:


(注意,所有服务都托管在 IIS 中)

门户服务(和 IIS 主机)

Portal.svc:
<%@ ServiceHost Service="System.ServiceModel.Routing.RoutingService, System.ServiceModel.Routing, version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
Web.config:

<configuration>
  <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <bindings>
      ...  
    </bindings>
    <client>
      <endpoint address="http://searcher1/Searcher.svc/general" binding="basicHttpBinding" contract="*" name="regularSearchServiceEndpoint" />
      <endpoint address="http://searcher2/Searcher.svc/general" binding="basicHttpBinding" contract="*" name="regularSearchServiceEndpoint2" />
    </client>
    <behaviors>
      ...
    </behaviors>
    <routing>
      <filters>
        <filter name="MatchAllFilter" filterType="MatchAll" />
      </filters>
      <filterTables>
        <filterTable name="filterTable1">
          <add filterName="MatchAllFilter" endpointName="regularSearchServiceEndpoint" backupList="backupList1" priority="0"/>
        </filterTable>
      </filterTables>
      <backupLists>
        <backupList name="backupList1">
          <add endpointName="regularSearchServiceEndpoint2"/>
        </backupList>
      </backupLists>
    </routing>
    <services>
      <service behaviorConfiguration="routingConfiguration" name="System.ServiceModel.Routing.RoutingService">
        <endpoint address="general" binding="basicHttpBinding" name="routerEndpoint1" contract="System.ServiceModel.Routing.IRequestReplyRouter" />
      </service>
    </services>
  </system.serviceModel>
</configuration>


搜索服务

ISearch.cs:

namespace SearchService
{
  [ServiceContract]
  public interface ISearch
  {
    [OperationContract]
    string Ping();
    [OperationContract]
    string searchByInput(string input);
  }
}

应用程序配置:

<configuration>
  <!-- When deploying the service library project, the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        ...
      </basicHttpBinding>
      <customBinding>
        ...
      </customBinding>
    </bindings>
    <client>
      ...
    </client>
    <services>
      <service name="SearchService.Search">
        <endpoint address="general" binding="basicHttpBinding" contract="SearchService.ISearch" name="SearchService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8732/Design_Time_Addresses/SearchService/Service1/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="False"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>


搜索服务主机

搜索.svc:
<%@ ServiceHost Service="SearchService.Search" %>
Web.config:

<configuration>
  <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <bindings>
      <basicHttpBinding>
        <!--copied over from SearchService.App.config-->
      </basicHttpBinding>
      <customBinding>
        <!--copied over from SearchService.App.config-->
      </customBinding>
    </bindings>
    <client>
      <!--copied over from SearchService.App.config-->
    </client>
    <services>
      ...
    </services>
    <behaviors>
      ...
    </behaviors>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>


客户(一切都出错了)

我能够让它做我想做的唯一方法是向搜索器服务添加一个 Web 服务引用(名为“remotehost”),然后手动将客户端端点添加到路由器的 app.config 文件中,然后强制客户端代码使用它,而不是它已经拥有的直接链接到搜索者

主要.cs:

namespace Client  
{  
  public partial class Main : Form  
  {  
    remotehost.SearchClient proxy;  
    public Main()  
    {  
      InitializeComponent();  
      proxy = new remotehost.SearchClient("RouterService");//("BasicHttpBinding_ISearch")  
    }  
    private void button1_Click(object sender,EventArgs e)  
    {  
      string response = string.Empty;
      //uses method exposed by the SearchService service
      response = proxy.Ping();
      MessageBox.Show("Response from remote service:\n" + response
        "Ping Response",
        MessageBoxButtons.OK,
        MessageBoxIcon.Information);
    }
  }
}

应用程序配置:

<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        ...
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://searcher1/Searcher.svc/general" binding="basicHttpBinding" bindingConfiguration="SearchService" contract="remotehost.ISearch" name="SearchService" />
      <!--I manually added this-->
      <endpoint address="http://portal/Portal.svc/general" binding="basicHttpBinding" contract="remotehost.ISearch" name="RouterService" />
    </client>
  </system.serviceModel>
</configuration>


我想强调,这一切都有效,但它并没有按照我想要的方式工作。我相当确定我可以将它推/拉/哄到我设想的优雅设置中,但我似乎无法找到第一次引导我完成它的资源或指南。

帮助?


我来这里之前咨询过的消息来源:

Learning WCF: A Hands-on Guide, by Bustamante, Michele Leroux {978-0-5961-0162-6} (read cover to cover, and did all exercises)  
Windows Communication Foundation 4: Step By Step {978-0-7356-4556-1} (focused on chapter 14: Discovering Services and Routing Messages)  
msdn.microsoft.com/en-us/library/ms734712.aspx {WCF: Getting Started Tutorial}  
msdn.microsoft.com/en-us/gg465212 {what's new in WCF4: exercises 8 & 9, content bridging & routing}  
codeproject.com/Articles/146835/How-to-create-scalable-services-with-WCF-4-0-Route {How to create scalable services with WCF 4.0 Router and Discovery services}  
msdn.microsoft.com/en-us/library/dd795218.aspx {Hello World with the Routing Service}  
msdn.microsoft.com/en-us/library/ee517421.aspx {routing}  
  msdn.microsoft.com/en-us/library/ee517423.aspx {routing service overview}  
  msdn.microsoft.com/en-us/library/ee517418.aspx {routine service features}  
  msdn.microsoft.com/en-us/library/ee517422.aspx {routing intro}  
  msdn.microsoft.com/en-us/library/ee517420.aspx {routing contracts}  
msdn.microsoft.com/en-us/library/bb332338.aspx {wcf routing}  
msdn.microsoft.com/en-us/library/ms730158.aspx {more wcf routing}  
msdn.microsoft.com/en-us/library/ee354381.aspx {more wcf routing}  
dandcohen.wordpress.com/2010/03/02/wcf-4-routing-service-multicast-sample/ {WCF 4 Routing Service Multicast sample}  

更新:2012-04-28:

我想出了一种方法来做我想做的事。它仍然没有我想要的那么优雅,但它完成了工作并让我继续前进。

基本上,从主服务中获取接口,并在一个新服务中实现它,称之为路由器或门户,或其他任何东西。在新的路由器/门户服务中,添加对主服务的新服务引用。

现在,两个服务都使用相同的接口,并且它们的所有方法都具有相同的签名,因此您可以将门户/路由器服务 wsdl 提供给第三方客户端,并且只允许您的门户/路由器服务与主要服务。

此外,如果您有多个主要服务,您可以使用门户/路由器服务来决定将请求发送到哪个主要服务,使用对它们的多个服务引用,并使用代理继续发送作业。它真的很好用。

它基本上是一个手动的前端路由服务,但美妙的是,详细的工作可以在线程模型的主要服务中完成,而看门的工作可以在门户/路由器上完成,因此只发送实际请求到主要服务,允许他们只做工作,门户服务决定他们如何或是否获得工作。下一步我想添加它自动发现新服务,但目前,手动配置工作正常。

如果有人想查看并请求它,我可以发布我想出的源代码。

4

1 回答 1

0

根本问题是路由器对服务正在使用的服务合同一无所知——它使用通用合同(使用 Message 类型的合同)。因此,路由器无法为客户端自动生成元数据。

您需要做的是自己提供元数据,可能作为静态 WSDL 文档,其中包含正确的地址并将客户端指向此

于 2012-04-19T06:19:38.487 回答