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 地址。 分配给此操作的时间可能是 更长的超时时间。

我也尝试设置&lt;AllowAllTraffic/&gt; 而不是&lt;WhenSource ...&gt;,但这没有效果。

第二次尝试: 经过一些反馈后,我尝试了一些变体,将FixedPortPortRange 设置为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 托管的 WCF 中找不到终结点

Azure 应用服务 - 从另一方收到不安全或不正确安全的故障。查看内部的 FaultException - Wcf

绝对路径不适用于 WCF 服务

代理类不适用于 Windows Phone 7 对 WCF 服务的引用

将服务器从 2012 升级到 2019 后,Web Socket 不适用于实际设备