工作者角色中的主机WCF,超时

时间:2015-04-09 10:50:47

标签: asp.net asp.net-mvc wcf azure

基本上,我跟着这个:GUIDE

我想要的是通过一个网络角色和一个工作人员角色将我的Cloudapp发布到azure。

工作人员角色

我在我的工作者角色中托管WCF服务,其中所有的sql通信都将发生,(DTO对象)。

网络角色

我的web角色项目只是一个普通的MVC应用程序,它具有对WCF服务的服务引用。例如,如果用户想要注册,则将数据发送到WCF服务,然后将其发送到数据库。

问题

错误讯息:

An exception of type 'System.ServiceModel.FaultException' occurred in mscorlib.dll but was not handled in user code

Additional information: The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework SDK documentation and inspect the server trace logs.

我还有一个超时错误,在此之前我似乎无法再现......

我非常彻底地遵循了指南。有一点不同的是,我想在一个出版物而不是两个出版物中托管它们。此外,该人通过点击我不会发布的软件包来发布项目(我点击发布按钮)。

我想出了所有的想法。我只找到了两个关于以工作者角色托管您的WCF服务的指南,我现在关注的那个和THIS一个。两者都非常过时,并没有真正做我想做的事情。这两个指南都将WCF服务作为独立的Cloudapp托管。我想要的是在同一个解决方案中发布辅助角色和Web角色,一个发布。

如果您有任何建议,请留在这里。我很感激能得到的所有帮助。非常感谢你。

/垂死的程序员

编辑1 - 代码 -

INTERFACE&amp;实施

namespace Fildela_Worker
{
    [ServiceContract]
    public interface IFildelaService
    {
        [OperationContract]
        void InsertUser(UserDTO user);
    }
}
[System.ServiceModel.ServiceBehaviorAttribute(IncludeExceptionDetailInFaults=tru‌​e)]
public class FildelaService : IFildelaService
    {
        DataLayer DB = new DataLayer();

        public void InsertUser(UserDTO user)
        {
            User newUser = new User(user.FirstName.ToLower().Trim(), user.LastName.ToLower().Trim(),
                user.Email.ToLower().Trim(), user.Password.Trim(), user.PasswordSalt.Trim(), user.AgreeUserAgreement);

            DB.User.Add(newUser);
            DB.SaveChanges();
        }
}

服务定义

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="Fildela_Web.Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2014-01.2.3">
  <WebRole name="Fildela Web" vmsize="Small">
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
  <WorkerRole name="Fildela Worker" vmsize="Small">
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
    <Endpoints>
      <InputEndpoint name="port" protocol="tcp" port="9001" />
      <InputEndpoint name="mexport" protocol="tcp" port="8001" />
    </Endpoints>
  </WorkerRole>
</ServiceDefinition>

工作角色ONSTART:

public override bool OnStart()
    {
        // Set the maximum number of concurrent connections 
        ServicePointManager.DefaultConnectionLimit = 12;

        // Create the host
        ServiceHost host = new ServiceHost(typeof(FildelaService));

        // Read config parameters
        string hostName = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["port"].IPEndpoint.Address.ToString();
        int port = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["port"].IPEndpoint.Port;
        int mexport = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["mexport"].IPEndpoint.Port;

        // Create Metadata
        ServiceMetadataBehavior metadatabehavior = new ServiceMetadataBehavior();
        host.Description.Behaviors.Add(metadatabehavior);

        Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
        string mexendpointurl = string.Format("net.tcp://{0}:{1}/FildelaServiceMetadata", hostName, 8001);
        host.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, mexendpointurl, new Uri(mexendpointurl));

        // Create end point
        string endpointurl = string.Format("net.tcp://{0}:{1}/FildelaService", hostName, 9001);
        host.AddServiceEndpoint(typeof(IFildelaService), new NetTcpBinding(SecurityMode.None), endpointurl, new Uri(endpointurl));

        // Open the host
        host.Open();

        // Trace output
        Trace.WriteLine("WCF Listening At: " + endpointurl);
        Trace.WriteLine("WCF MetaData Listening At: " + mexendpointurl);

        return base.OnStart();
    }

MVC WEB.CONFIG:

<system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="NetTcpBinding_IFildelaService">
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="net.tcp://MYADDRESS.cloudapp.net:9001/FildelaService"
        binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IFildelaService"
        contract="FildelaServiceReference.IFildelaService" name="NetTcpBinding_IFildelaService" />
    </client>
....

MVC PROXY USE:

FildelaServiceClient proxy = new FildelaServiceClient();

                                UserDTO newUser = new UserDTO()
                                {
parameters....
                                };

                                //Insert user
proxy.InsertAccountOwner(newUser);

编辑2 - 代码 -

工作人员角色

public override bool OnStart()
    {
        // Set the maximum number of concurrent connections 
        ServicePointManager.DefaultConnectionLimit = 12;

        StartWCFHost();

        return base.OnStart();
    }

private void StartWCFHost()
{
    var baseaddress = string.Format("net.tcp://{0}/", RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["FildelaService"].IPEndpoint);
    var host = new ServiceHost(typeof(FildelaService), new Uri(baseaddress));
    host.AddServiceEndpoint(typeof(IFildelaService), new NetTcpBinding(SecurityMode.None), "Database");
    host.Open();
}

服务定义

<WorkerRole name="Fildela Worker" vmsize="Small">
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
    <Endpoints>
      <InternalEndpoint name="FildelaService" protocol="tcp" />
    </Endpoints>
  </WorkerRole>

控制器

private EndpointAddress GetRandomEndpoint()
    {
        var endpoints = RoleEnvironment.Roles["Fildela Worker"].Instances.Select(i => i.InstanceEndpoints["FildelaService"].IPEndpoint).ToArray();
        var r = new Random(DateTime.Now.Millisecond);
        return new EndpointAddress(string.Format("net.tcp://{0}/Database", endpoints[r.Next(endpoints.Count() - 1)]));
    }





[HttpGet]
    [AllowAnonymous]
    public ViewResult Contact()
    {
        var factory = new ChannelFactory<IFildelaService>(new NetTcpBinding(SecurityMode.None));
        factory.Endpoint.Binding.SendTimeout = new TimeSpan(0, 5, 0);
        var channel = factory.CreateChannel(GetRandomEndpoint());

        List<CategoryDTO> contactCategories = channel.GetContactCategories().ToList();

        return View(contactCategories);
    }

1 个答案:

答案 0 :(得分:1)

首先,您有合同和服务,托管您的服务删除您添加到OnStart方法的所有代码并添加此方法

 private void StartWCFHost()
    {
        var baseaddress = string.Format("net.tcp://{0}/", RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["port"].IPEndpoint);
        var host = new ServiceHost(typeof(FildelaService), new Uri (baseaddress));
        host.AddServiceEndpoint(typeof(IFildelaService), new NetTcpBinding(SecurityMode.None), "Inserter");
        host.Open();
    }

即只是从OnStart方法调用此方法并且主机已完成

现在的问题是关于使用网络服务

当您调用webservice时,在控制器中

添加此代码(我们正在创建一个Channel工厂,无需添加服务引用)

首先将此方法添加到您的控制器

 private EndpointAddress GetRandomEndpoint()
    {
        var endpoints= RoleEnvironment.Roles["PutWorkerRoleName"].Instances.Select(i=>i.InstanceEndpoints["port"].IPEndpoint).ToArray();
        var r = new Random(DateTime.Now.Millisecond);
        return new EndpointAddress(string.Format("net.tcp://{0}/Inserter", endpoints[r.Next(endpoints.Count() - 1)]));
    }

然后添加此代码以在您的控制器方法中调用服务(因为您正在使用MVC)

 var factory = new ChannelFactory<IFildelaService>(new NetTcpBinding(SecurityMode.None));
        var channel = factory.CreateChannel(GetRandomEndpoint());
        channel.InsertAccountOwner(newUser);

我可能忘记从我的工作项目中重命名一些变量,因此可以随意验证代码的一致性

<强>更新

我将项目上传到我的github: Worker Role WCF host+Web Role