2017-02-06 12 views
7

Birden çok bağlantı noktasını dinlemek için bir hizmet kumaşı uygulaması bağlamak mümkün mü?Service-Fabric Birden çok son noktaya bağlama

Temel olarak, http: 80 ve https: 443 dinleyen ve http isteklerini https'ye yönlendiren bir kamu hizmetine sahip olmaya çalışıyorum.

Yeni bir ASP.net Core hizmeti oluşturdum, tek tek gayet iyi çalışıyor. Yani SSL 443 veya sadece SSL olmayan 80 ile, ancak ServiceInstanceListeners her ikisini de eklediğimde başarısız oluyor! - öylesine görünüyor hem dinleyiciler farklı adlara sahip olduğundan garip

Unhealthy event: SourceId='System.RA', Property='ReplicaOpenStatus', HealthState='Warning', ConsiderWarningAsError=false. 
Replica had multiple failures in API call: IStatelessServiceInstance.Open(); Error = System.Fabric.FabricElementAlreadyExistsException (-2146233088) 
Unique Name must be specified for each listener when multiple communication listeners are used 
    at Microsoft.ServiceFabric.Services.Communication.ServiceEndpointCollection.AddEndpointCallerHoldsLock(String listenerName, String endpointAddress) 
    at Microsoft.ServiceFabric.Services.Communication.ServiceEndpointCollection.AddEndpoint(String listenerName, String endpointAddress) 
    at Microsoft.ServiceFabric.Services.Runtime.StatelessServiceInstanceAdapter.d__13.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at Microsoft.ServiceFabric.Services.Runtime.StatelessServiceInstanceAdapter.d__0.MoveNext() 

:

Servis Kumaş Explorer birkaç kez zaman aşımına uğradıktan sonra aşağıdaki hatayı söylüyor. Kaçırdığım dinleyici adını koymam gereken bir yer var mı?

Bunun için Asp.net Core şablonunu kullanıyorum. şöyle My Vatansız Servis kodudur:

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 ServiceInstanceListener[] 
     { 
      new ServiceInstanceListener(serviceContext => 
       new WebListenerCommunicationListener(serviceContext, "ServiceEndpointHttps", url => 
       { 
        ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting WebListener on {url}"); 

        return new WebHostBuilder() 
           .UseWebListener() 
           .ConfigureServices(
            services => services 
             .AddSingleton<StatelessServiceContext>(serviceContext)) 
           .UseContentRoot(Directory.GetCurrentDirectory()) 
           .UseStartup<Startup>() 
           .UseUrls(url) 
           .Build(); 
       })), 


      new ServiceInstanceListener(serviceContext => 
       new WebListenerCommunicationListener(serviceContext, "ServiceEndpointHttp", url => 
       { 
        ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting WebListener on {url}"); 

        return new WebHostBuilder() 
           .UseWebListener() 
           .ConfigureServices(
            services => services 
             .AddSingleton<StatelessServiceContext>(serviceContext)) 
           .UseContentRoot(Directory.GetCurrentDirectory()) 
           .UseStartup<Startup>() 
           .UseUrls(url) 
           .Build(); 
       })) 
     }; 
    } 
} 

cevap

6

Ben yapıcı sahiptir ServiceInstanceListener üzerine adını ayarlamak için gerekli

public ServiceInstanceListener(Func<StatelessServiceContext, ICommunicationListener> createCommunicationListener, string name = ""); 

Ben ekstra params :)

+1

Bu ad hizmetiniz için ayarlarınızdaki bitiş noktasının adıyla eşleşmelidir. Tek bir uç noktaya sahip bir servis için boş bırakmanız yeterlidir, ancak birden fazla alana sahip olduğunuzda bunları isimle tanımlamanız gerekir. – yoape

+1

Bilmekte fayda var, teşekkürler! Gelecekte beni rahatsız etmeyecek. – Mardoxx

1

You olduğunu fark etmemiştim Aşağıdaki kodu kullanarak tüm bunları otomatik hale getirebilir ve gerekli olan yerlerde gerekli bilgileri de kaydedebilir.

var currentEndpoint = ""; 
try 
{ 
    IList<ServiceInstanceListener> listeners = new List<ServiceInstanceListener>(); 
    var endpoints = FabricRuntime.GetActivationContext().GetEndpoints(); 

    foreach (var endpoint in endpoints) 
    { 
    currentEndpoint = endpoint.Name; 
    logger.LogInformation("Website trying to LISTEN : " + currentEndpoint); 

    var webListner = new ServiceInstanceListener(serviceContext => 
     new WebListenerCommunicationListener(serviceContext, endpoint.Name, (url, listener) => 
     { 
     url = endpoint.Protocol + "://+:" + endpoint.Port; 
     logger.LogInformation("Website Listening : " + currentEndpoint); 
     return new WebHostBuilder().UseWebListener()  .UseContentRoot(Directory.GetCurrentDirectory()) 
       .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None) 
       .UseStartup<Startup>() 
       .UseUrls(url) 
       .Build(); 
     }), endpoint.Name.ToString()); 
    listeners.Add(webListner); 
    } 
    return listeners; 
} 
catch (Exception ex) 
{ 
    logger.LogError("Exception occured while listening endpoint: " + currentEndpoint, ex); 
    throw; 
} 
+0

fwiw, "url" aslında "endpoint.Protocol +": // +: "+ endpoint.Port;' 'olarak ayarlanmış gibi görünüyor, bu yüzden bu kısmı yapmak zorunda kalmadım. Detaylı cevap için teşekkürler! – JohnnyFun

İlgili konular