问题描述:

I have two web roles and one of them runs the service layer consisting of 3 WCF services connected with net.tcp, each deployed as a website on port 808, 810, and 811.

Now I want the service layer to only be open to my other web role.

So I tried to make one of the services endpoint internal and to give access for my front web role.

Like this:

<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>

But when the UserService is attempted it seems to time out.

Server Error in '/' Application.

Connecting to via

net.tcp://myservicename.cloudapp.net:811/UserTypeService.svc timed out

after 00:00:00. Connection attempts were made to 0 of 1 available

addresses (). Check the RemoteAddress of your channel and verify that

the DNS records for this endpoint correspond to valid IP Addresses.

The time allotted to this operation may have been a portion of a

longer timeout.

I have also tried to set <AllowAllTraffic/> instead of <WhenSource ...> but that has no effect.

Second attempt:

After some feedback I have tried some variations to set a FixedPort and PortRange to 811 and the role listening to port="*".

<InternalEndpoint name="Endpoint6" protocol="tcp" port="*" >

<FixedPortRange min="811" max="811"></FixedPortRange>

</InternalEndpoint>

I have kept the NetworkTrafficRules as in previous attempts.

I also added the following code to make sure there is a listener for a dynamic port. In my WebRole.cs file:

 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} Remote{1}",

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();

}

}

Another note is that the calling service uses port 811 to find the right service since the service runs three different WCF project sites. And the service I'm calling also uses a specified port number which I think can be a problem if it all of a sudden should be dynamic. The calling service looks like this:

<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>

And on the receiving(Internal) WebRole sites I have the following types of configurations.

<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>

And the other WCF site on port 811:

<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>

网友答案:

You could use the internal endpoint IP-addresses and instead of the external address. Here is an example:

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);

        }
    }
}
相关阅读:
Top