WCF 服务的内部终结点不适用于 Azure Web 角色
Posted
技术标签:
【中文标题】WCF 服务的内部终结点不适用于 Azure Web 角色【英文标题】:Internal endpoint for WCF service dont work on Azure Web role 【发布时间】:2015-12-08 19:21:10 【问题描述】:我有两个 Web 角色,其中一个运行服务层,该服务层由 3 个与 net.tcp 连接的 WCF 服务组成,每个服务都部署为端口 808、810 和 811 上的网站。
现在我希望服务层只对我的其他 Web 角色开放。
所以我尝试将服务端点之一设为内部并为我的前端 Web 角色提供访问权限。
像这样:
<ServiceDefinition name="MagnusAzureCloudService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2015-04.2.6">
<WebRole name="Core.Services" vmsize="Small">
<Runtime executionContext="elevated" />
<Startup>
<Task commandLine="Startup/startup.cmd" executionContext="elevated" taskType="background" />
</Startup>
<Sites>
<Site name="Core" physicalDirectory="C:\CoreServices">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
</Bindings>
</Site>
<Site name="Store" physicalDirectory="C:\StoreServices">
<Bindings>
<Binding name="Endpoint3" endpointName="Endpoint3" />
</Bindings>
</Site>
<Site name="Users" physicalDirectory="C:\UserServices">
<Bindings>
<Binding name="Endpoint4" endpointName="Endpoint4" />
</Bindings>
</Site>
</Sites>
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" />
</ConfigurationSettings>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="8282" />
<InputEndpoint name="Endpoint3" protocol="http" port="81" />
<InputEndpoint name="Endpoint4" protocol="http" port="8181" />
<InputEndpoint name="Endpoint2" protocol="tcp" port="808" localPort="808" />
<InputEndpoint name="Endpoint5" protocol="tcp" port="810" localPort="810" />
<InternalEndpoint name="Endpoint6" protocol="tcp" port="811" />
</Endpoints>
<Certificates>
</Certificates>
<Imports>
<Import moduleName="RemoteAccess" />
<Import moduleName="RemoteForwarder" />
</Imports>
</WebRole>
<WebRole name="UIWeb" vmsize="Small">
<Runtime executionContext="elevated" />
<Startup>
<Task commandLine="Startup/startup.cmd" executionContext="elevated" taskType="background" />
</Startup>
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
</Bindings>
</Site>
</Sites>
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" />
</ConfigurationSettings>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
</Endpoints>
<Imports>
<Import moduleName="RemoteAccess" />
</Imports>
</WebRole>
<NetworkTrafficRules>
<OnlyAllowTrafficTo>
<Destinations>
<RoleEndpoint endpointName="Endpoint6" roleName="Core.Services" />
</Destinations>
<WhenSource matches="AnyRule">
<FromRole roleName="UIWeb"/>
</WhenSource>
</OnlyAllowTrafficTo>
</NetworkTrafficRules>
</ServiceDefinition>
但是当尝试 UserService 时,它似乎超时了。
“/”应用程序中的服务器错误。
通过连接 net.tcp://myservicename.cloudapp.net:811/UserTypeService.svc 超时 00:00:00 之后。对 1 个可用的 0 个进行了连接尝试 地址()。检查您的频道的 RemoteAddress 并验证 此端点的 DNS 记录对应于有效的 IP 地址。 分配给此操作的时间可能是 更长的超时时间。
我也尝试设置<AllowAllTraffic/>
而不是<WhenSource ...>
,但这没有效果。
第二次尝试:
经过一些反馈后,我尝试了一些变体,将FixedPort
和PortRange
设置为811,并且监听port="*"
的角色。
<InternalEndpoint name="Endpoint6" protocol="tcp" port="*" >
<FixedPortRange min="811" max="811"></FixedPortRange>
</InternalEndpoint>
我像以前的尝试一样保留了 NetworkTrafficRules。
我还添加了以下代码以确保有一个动态端口的侦听器。在我的 WebRole.cs 文件中:
public class WebRole : RoleEntryPoint
/// <summary>
///
/// </summary>
/// <returns></returns>
public override bool OnStart()
Trace.TraceInformation("OnStart method called. Updating information on IIS.");
try
// Initialize method-wide variables
var epName = "Endpoint6";
var roleInstance = RoleEnvironment.CurrentRoleInstance;
// Identify direct communication port
var myPublicEp = roleInstance.InstanceEndpoints[epName].PublicIPEndpoint;
Trace.TraceInformation("IP:0, Port:1", myPublicEp.Address, myPublicEp.Port);
// Identify public endpoint
var myInternalEp = roleInstance.InstanceEndpoints[epName].IPEndpoint;
// Create socket listener
var listener = new Socket(
myInternalEp.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
// Bind socket listener to internal endpoint and listen
listener.Bind(myInternalEp);
listener.Listen(10);
Trace.TraceInformation("Listening on IP:0,Port: 1",
myInternalEp.Address, myInternalEp.Port);
while (true)
// Block the thread and wait for a client request
Socket handler = listener.Accept();
Trace.TraceInformation("Client request received.");
// Define body of socket handler
var handlerThread = new Thread(
new ParameterizedThreadStart(h =>
var socket = h as Socket;
Trace.TraceInformation("Local:0 Remote1",
socket.LocalEndPoint, socket.RemoteEndPoint);
// Shut down and close socket
socket.Shutdown(SocketShutdown.Both);
socket.Close();
));
// Start socket handler on new thread
handlerThread.Start(handler);
catch (Exception e)
Trace.TraceError("Caught exception in run. Details: 0", e);
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;
return base.OnStart();
另一个注意事项是调用服务使用端口 811 来查找正确的服务,因为该服务运行三个不同的 WCF 项目站点。而且我正在调用的服务还使用指定的端口号,如果它突然应该是动态的,我认为这可能是一个问题。调用服务如下所示:
<endpoint address="net.tcp://myservicename.cloudapp.net:811/UserTypeService.svc"
behaviorConfiguration="ClientContextEndpointBehavior" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_FrameworkService" contract="Users.Services.IPersonTypeService"
name="Tcp">
<identity>
<dns value="The Certificate Name" />
</identity>
</endpoint>
在接收(内部)WebRole 网站上,我有以下类型的配置。
<service name="Core.Services.Logging.LoggingService" behaviorConfiguration="coreServiceBehavior">
<endpoint address="net.tcp://localhost:808/LoggingService.svc"
behaviorConfiguration="ContextEndpointBehavior"
binding="netTcpBinding"
bindingConfiguration="NetTcpBinding1"
contract="Core.Logging.ILoggingService">
<identity>
<dns value="The Certificate Name" />
</identity>
</endpoint>
以及端口 811 上的其他 WCF 站点:
<service name="Users.Services.PersonTypeService">
<endpoint address="net.tcp://localhost:811/UserTypeService.svc" binding="netTcpBinding" bindingConfiguration="NetTcpServiceBinding1" behaviorConfiguration="ServerContextEndpointBehavior" contract="Users.Services.IUserTypeService">
<identity>
<dns value="The Certificate Name" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" kind="mexEndpoint">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
【问题讨论】:
【参考方案1】:您可以使用内部端点 IP 地址而不是外部地址。这是一个例子:
foreach (RoleInstance roleInst in RoleEnvironment.CurrentRoleInstance.Role.Instances)
// Skip local role instance
if (RoleEnvironment.CurrentRoleInstance.Id == roleInst.Id) continue;
if (roleInst.Role.Name == "My Cool Role")
foreach (RoleInstanceEndpoint roleInstEndpoint in roleInst.InstanceEndpoints.Values)
// Get endpoint address using the internal endpoint's IP address
if (roleInstEndpoint.Protocol == "tcp")
SendRequest(roleInstEndpoint.IPEndpoint.Address.ToString(), command);
【讨论】:
我不确定我是否在关注?你建议我做什么,为什么? @MagnusKarlsson 您正在尝试使用 external 地址 myservicename.cloudapp.net 连接到 internal 端点到您的服务,Input端点 用于与 Azure 外部 的角色实例进行通信。 内部端点用于internal角色通信,然后您需要内部IP范围的IP地址,这是我的编码示例所做的,有关更多信息,请参阅msdn.microsoft.com/en-us/library/azure/hh180158.aspx 我认为 Azure 内部 DNS 将处理我的云服务地址并将其解析为正确的 IP 地址。由于这两个角色在同一个云服务中,他们应该能够在没有工作的情况下相互交谈吗?在这个例子中,我刚刚添加了一个固定端口,现在就试试看。还是我错过了什么? msdn.microsoft.com/en-us/library/azure/hh180158.aspx 我在实现绑定部分后更新了问题。我想这就像你建议的那样。改为使用文档页面中的代码。我对如何针对特定端口设置我的服务也有一些考虑。以上是关于WCF 服务的内部终结点不适用于 Azure Web 角色的主要内容,如果未能解决你的问题,请参考以下文章
将本地 WCF 服务迁移到 Windows Azure 需要考虑的事项
Azure 应用服务 - 从另一方收到不安全或不正确安全的故障。查看内部的 FaultException - Wcf