多年来,我一直使用 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 提供给第三方客户端,并且只允许您的门户/路由器服务与主要服务。
此外,如果您有多个主要服务,您可以使用门户/路由器服务来决定将请求发送到哪个主要服务,使用对它们的多个服务引用,并使用代理继续发送作业。它真的很好用。
它基本上是一个手动的前端路由服务,但美妙的是,详细的工作可以在线程模型的主要服务中完成,而看门的工作可以在门户/路由器上完成,因此只发送实际请求到主要服务,允许他们只做工作,门户服务决定他们如何或是否获得工作。下一步我想添加它自动发现新服务,但目前,手动配置工作正常。
如果有人想查看并请求它,我可以发布我想出的源代码。