C# 如何在服务结构上浏览应用程序?

C# 如何在服务结构上浏览应用程序?,c#,.net,asp.net-web-api,visual-studio-2017,azure-service-fabric,C#,.net,Asp.net Web Api,Visual Studio 2017,Azure Service Fabric,如何找出触发GetAccounts需要请求的端点? 我的本地群集上运行了两个应用程序: 结构/服务是具有以下配置的web api应用程序: internal sealed class Web : StatelessService { public Web(StatelessServiceContext context) : base(context) { } /// <summary>

如何找出触发GetAccounts需要请求的端点?

我的本地群集上运行了两个应用程序:

结构/服务是具有以下配置的web api应用程序:

internal sealed class Web : StatelessService
    {
        public Web(StatelessServiceContext context)
            : base(context)
        {
        }

        /// <summary>
        ///     Optional override to create listeners (like tcp, http) for this service instance.
        /// </summary>
        /// <returns>The collection of listeners.</returns>
        protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
        {
            return new[]
            {
                new ServiceInstanceListener(serviceContext => new OwinCommunicationListener(Startup.ConfigureApp,
                    serviceContext, ServiceEventSource.Current, "ServiceEndpoint"))
            };
        }
    }
内部密封类Web:无状态服务
{
公共Web(无状态ServiceContext上下文)
:基本(上下文)
{
}
/// 
///可选覆盖,用于为此服务实例创建侦听器(如tcp、http)。
/// 
///听众的集合。
受保护的重写IEnumerable CreateServiceInstanceListeners()
{
返回新的[]
{
新ServiceInstanceListener(serviceContext=>新的OwinCommunicationListener(Startup.ConfigureApp,
serviceContext,ServiceEventSource.Current,“ServiceEndpoint”))
};
}
}
启动配置如下:

public static class Startup
{
    // This code configures Web API. The Startup class is specified as a type
    // parameter in the WebApp.Start method.

    public static void ConfigureApp(IAppBuilder appBuilder)
    {
        // Configure Web API for self-host. 
        var config = new HttpConfiguration();
        //config.Routes.MapHttpRoute(
        //    name: "DefaultApi",
        //    routeTemplate: "api/{controller}/{id}",
        //    defaults: new { id = RouteParameter.Optional }
        //);
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
        config.MapHttpAttributeRoutes();
        var container = new UnityContainer();
        container.RegisterType<IAccountService, AccountService>(new HierarchicalLifetimeManager());
        config.DependencyResolver = new UnityResolver(container);

        appBuilder.UseWebApi(config);
    }
}
公共静态类启动
{
//此代码配置Web API。启动类被指定为类型
//WebApp.Start方法中的参数。
公共静态无效配置应用程序(IAppBuilder appBuilder)
{
//为自主机配置Web API。
var config=新的HttpConfiguration();
//config.Routes.MapHttpRoute(
//名称:“DefaultApi”,
//routeTemplate:“api/{controller}/{id}”,
//默认值:新建{id=RouteParameter.Optional}
//);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(新的MediaTypeHeaderValue(“text/html”);
config.maphttpAttribute路由();
var container=new UnityContainer();
RegisterType(新的层次结构CallifetimeManager());
config.DependencyResolver=新的UnityResolver(容器);
appBuilder.UseWebApi(配置);
}
}
最后是服务清单:

<?xml version="1.0" encoding="utf-8"?>

<ServiceManifest Name="WebPkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <!-- This is the name of your ServiceType. 
         This name must match the string used in RegisterServiceType call in Program.cs. -->
    <StatelessServiceType ServiceTypeName="WebType" />
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>removed...........Accounts.Web.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
  </CodePackage>

  <!-- Config package is the contents of the Config directoy under PackageRoot that contains an 
       independently-updateable and versioned set of custom configuration settings for your service. -->
  <ConfigPackage Name="Config" Version="1.0.0" />

  <Resources>
    <Endpoints>
      <!-- This endpoint is used by the communication listener to obtain the port on which to 
           listen. Please note that if your service is partitioned, this port is shared with 
           replicas of different partitions that are placed in your code. -->
      <Endpoint Protocol="http" Name="ServiceEndpoint" Type="Input" />
    </Endpoints>
  </Resources>
</ServiceManifest>

已删除……….Accounts.Web.exe
代码包
和我的控制器:

    [HttpGet]
    [Route("accounts", Name = "GetAccounts")]
    public async Task<IHttpActionResult> GetAccounts(){//dostuff}
[HttpGet]
[路由(“帐户”,Name=“GetAccounts”)]
公共异步任务GetAccounts(){//dostuff}

我如何找出应该请求什么端点来触发GetAccounts?

我想这个Web Api是对外公开的? 您用来承载它的无状态服务已启用动态端口。 对于面向外部的服务,最好为其提供一个固定端口

在服务清单文件中,您可以在端点定义中添加端口号:

<Endpoint Protocol="http" Name="ServiceEndpoint" Type="Input" Port="80">

有关更多信息,请参阅

获得端口号后,您可以在以下位置访问web api:

然后,无论是否使用动态端口,都可以在资源管理器中查找实际端口号

要查看端点端口号,请浏览到服务下面的节点,如下所示:

(请参见右侧的端点?)


请注意,如果端点包含特定节点的ip,则需要集群的ip或FQDN。但现在看来还可以,因为您使用的是localhost

服务结构提供了内置的。默认情况下,它在本地开发集群中启用。反向代理允许您使用动态端口(如.gif所示)。使用反向代理时,您可以使用反向代理的端口号(默认为19081)调用服务。您的用例中的地址格式是带有单例分区的无状态服务,它是:
protocol://clusterAddress:reverseProxyPort/applicationName/serviceName

在您的示例中,服务将通过以下方式调用:
http://clusterAddress:19081/Service/Web/api/controller/accounts/GetAccounts

在服务结构中,服务运行在服务结构集群中的某个位置,通常分布在多个虚拟机上。它可以由服务所有者或服务结构自动从一个位置移动到另一个位置。服务不是静态地绑定到特定的机器或地址

服务结构应用程序通常由许多不同的服务组成,其中每个服务执行一个专门的任务。这些服务可以相互通信以形成完整的功能,例如呈现web应用程序的不同部分。还有一些客户端应用程序连接到服务并与之通信

例如,为了在端口80上接受外部通信,必须配置以下内容: 编写侦听端口80的服务。在服务的ServiceManifest.xml中配置端口80,并在服务中打开侦听器,例如,自托管web服务器

XML


C#

HttpCommunicationListener类:ICommunicationListener { ... 公共任务OpenAsync(CancellationToken CancellationToken) { EndpointResourceDescription端点= serviceContext.CodePackageActivationContext.GetEndpoint(“WebEndpoint”); 字符串URI前缀=$“{endpoint.Protocol}://+:{endpoint.Port}/myapp/”; this.httpListener=新的httpListener(); this.httpListener.Prefixes.Add(uriPrefix); this.httpListener.Start(); 字符串publishUri=uriPrefix.Replace(“+”,FabriRuntime.GetNodeContext().IPAddressOrFQDN); 返回Task.FromResult(publishUri); } ... } 类WebService:无状态服务 { ... 受保护的重写IEnumerable CreateServiceInstanceListeners() { 返回new[]{new ServiceInstanceListener(context=>new-HttpCommunicationListener(context))}; } ... } 本文档讨论如何在Service Fabric中设置与服务之间的通信:


彼得,非常感谢你的帮助。我完全按照你的建议做了
<Resources>
    <Endpoints>
        <Endpoint Name="WebEndpoint" Protocol="http" Port="80" />
    </Endpoints>
</Resources>
class HttpCommunicationListener : ICommunicationListener
    {
        ...

        public Task<string> OpenAsync(CancellationToken cancellationToken)
        {
            EndpointResourceDescription endpoint =
                serviceContext.CodePackageActivationContext.GetEndpoint("WebEndpoint");

            string uriPrefix = $"{endpoint.Protocol}://+:{endpoint.Port}/myapp/";

            this.httpListener = new HttpListener();
            this.httpListener.Prefixes.Add(uriPrefix);
            this.httpListener.Start();

            string publishUri = uriPrefix.Replace("+", FabricRuntime.GetNodeContext().IPAddressOrFQDN);
            return Task.FromResult(publishUri);
        }

        ...
    }

class WebService : StatelessService
    {
        ...

        protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
        {
            return new[] { new ServiceInstanceListener(context => new HttpCommunicationListener(context))};
        }

        ...
    }