Defining Listeners - coherentsolutionsinc/aspnetcore-service-fabric-hosting GitHub Wiki
The ASP.NET Core listener is defined using DefineAspNetCoreListener(...)
method:
new HostBuilder()
.DefineStatefulService(
serviceBuilder =>
{
serviceBuilder.DefineAspNetCoreListener(listenerBuilder => { ... });
})
.Build()
.Run()
The Remoting listener is defined using DefineRemotingListener(...)
method:
new HostBuilder()
.DefineStatefulService(
serviceBuilder =>
{
serviceBuilder.DefineRemotingListener(listenerBuilder => { ... });
})
.Build()
.Run()
The Generic listener is defined using DefineGenericListener(...)
method:
new HostBuilder()
.DefineStatefulService(
serviceBuilder =>
{
serviceBuilder.DefineGenericListener(listenerBuilder => { ... });
})
.Build()
.Run()
You can define multiple listeners of any type. This is done using multiple calls to DefineAspNetCoreListener(...)
, DefineRemotingListener(...)
or DefineGenericListener(...)
methods:
new HostBuilder()
.DefineStatefulService(
serviceBuilder =>
{
serviceBuilder.DefineAspNetCoreListener(listenerBuilder => { ... });
serviceBuilder.DefineAspNetCoreListener(listenerBuilder => { ... });
serviceBuilder.DefineRemotingListener(listenerBuilder => { ... });
serviceBuilder.DefineRemotingListener(listenerBuilder => { ... });
serviceBuilder.DefineGenericListener(listenerBuilder => { ... });
serviceBuilder.DefineGenericListener(listenerBuilder => { ... });
})
.Build()
.Run()
All listeners has to be linked to the one of the endpoints declared in ServiceManifest.xml
.
<ServiceManifest Name="ServicePkg" Version="1.0.0">
<Resources>
<Endpoints>
<!-- @Name is the endpoint name. -->
<Endpoint Name="ServiceEndpoint" ... />
</Endpoints>
</Resources>
</ServiceManifest>
The linkage is done using UseEndpoint(...)
method:
...
.Define<any listener>Listener(
listenerBuilder =>
{
// The value matches the @Name in ServiceManifest.xml
listenerBuilder.UseEndpoint("ServiceEndpoint");
})
...
Warning
Linking to endpoint also automatically instructs infrastructure to consume configuration of the endpoint declared in
ServiceManifest.xml
. This sets the name of theICommunicationListener
to the name of the endpoint.
The configuration starts using DefineAspNetCoreListener(...)
method:
new HostBuilder()
.DefineStatefulService(
serviceBuilder =>
{
serviceBuilder.DefineAspNetCoreListener(listenerBuilder => { ... });
})
.Build()
.Run()
You can configure what server implementation (Kestrel
or HttpSys
) will be used to run IWebHost
. This is done using UseKestrel(...)
or UseHttpSys(...)
methods:
...
.DefineAspNetCoreListener(
listenerBuilder =>
{
listenerBuilder.UseKestrel();
listenerBuilder.UseKestrel(options => { ... }) // <-- 'with options';
listenerBuilder.UseHttpSys();
listenerBuilder.UseHttpSys(options => { ... }) // <-- 'with options';
})
...
Both methods have a separate overload that allows to supply KestrelServerOptions or HttpSysOptions options.
Warning
This settings implicitly overrides
IWebHost
server even if it was explicitly defined inside ConfigureWebHost(...) method.
Service Fabric provides a special middleware for AspNetCoreListener. This middleware can be installed using UseUniqueServiceUrlIntegration(...)
or UseReverseProxyIntegration(...)
methods.
...
.DefineAspNetCoreListener(
listenerBuilder =>
{
listenerBuilder.UseUniqueServiceUrlIntegration();
})
.DefineAspNetCoreListener(
listenerBuilder =>
{
listenerBuilder.UseReverseProxyIntegration();
})
...
Warning
You can't install multiple middleware on the same listener.
The IWebHost
is configured using ConfigureWebHost(...)
method:
...
.DefineAspNetCoreListener(
listenerBuilder =>
{
listenerBuilder.ConfigureWebHost(webHostBuilder => { ... })
})
...
When configuring IWebHost
it is important to remember that it will be executed within Service Fabric and therefore some of the configuration will be set by the infrastructure.
Here is a table of methods overrides:
Method | Description |
---|---|
UseUrls | Calls to UseUrls are overridden by the information of the endpoint resource from ServiceManifest.xml . |
UseKestrel | Calls to UseKestrel are overridden by usage of listenerBuilder.UseKestrel() or listenerBuilder.UseHttpSys() . |
UseHttpSys | Calls to UseHttpSys are overridden by usage of listenerBuilder.UseKestrel() or listenerBuilder.UseHttpSys() . |
UseServiceFabricIntegration | Calls to UseServiceFabricIntegration are overridden by usagelistenerBuilder.UseUniqueServiceUrlIntegration() or listenerBuilder.UseReverseProxyIntegration() . |
The configuration starts using DefineRemotingListener(...)
method:
new HostBuilder()
.DefineStatefulService(
serviceBuilder =>
{
serviceBuilder.DefineRemotingListener(listenerBuilder => { ... });
})
.Build()
.Run()
You can customize FabricTransportRemotingListenerSettings using UseSettings(...)
method:
...
.DefineRemotingListener(
listenerBuilder =>
{
listenerBuilder.UseSettings(() => new FabricTransportRemotingListenerSettings()));
})
...
It is important to remember when providing custom FabricTransportRemotingListenerSettings
that some of the settings will be set by the infrastructure.
Here is a table a methods overrides:
Property | Overrides |
---|---|
EndpointResourceName | Value of EndpointResourceName property is overridden by call to listenerBuilder.UseEndpoint(...) method. |
You can use custom implementation of IServiceRemotingMessageSerializationProvider.
This is done using UseSerializationProvider<TSerializationProvider>(...)
method:
...
.DefineRemotingListener(
listenerBuilder =>
{
listenerBuilder.UseSerializationProvider<TSerializationProvider>(); // <-- as 'type'
listenerBuilder.UseSerializationProvider<TSerializationProvider>(() => new SerializationProviderImpl()); // <-- as 'factory function'
listenerBuilder.UseSerializationProvider<TSerializationProvider>(provider => new SerializationProviderImpl()); // <-- as 'factory function with dependency injection'
})
...
Information
When
IServiceRemotingMessageSerializationProvider
is configured 'as type' all its parameters are automatically resolved using dependency injection.
You can use custom implementation of IServiceRemotingMessageHandler.
This is done using UseHandler<THandler>(...)
method:
...
.DefineRemotingListener(
listenerBuilder =>
{
listenerBuilder.UseHandler<THandler>(); // <-- as 'type'
listenerBuilder.UseHandler<THandler>(() => new HandlerImpl()); // <-- as 'factory function'
listenerBuilder.UseHandler<THandler>(provider => new HandlerImpl()); // <-- as 'factory function with dependency injection'
})
...
Information
When
IServiceRemotingMessageSerializationProvider
is configured 'as type' all its parameters are automatically resolved using dependency injection.
The implementation of IServiceRemotingMessageHandler
requires an instance of IService
implementation. The implementation instance can be obtained using dependency injection by requesting dependency as IService
or as implementation type:
...
public class MessageHandlerImpl : IServiceRemotingMessageHandler
{
public MessageHandlerImpl(
IService asIService,
ApiServiceImpl asImplementationType)
{
...
}
}
The remoting implementation consists from an interface
inherited from IService
and implementation class
.
public interface IApiService : IService
{
Task<string> GetVersionAsync();
}
public class ApiServiceImpl : IApiService
{
public ApiServiceImpl(ServiceContext context, ICustomService service)
{
...
}
public Task<string> GetVersionAsync()
{
return Task.FromResult("1.0");
}
}
The implementation is configured using UseImplementation<TImplementation>(...)
method:
...
.DefineRemotingListener(
listenerBuilder =>
{
listenerBuilder.UseImplementation<ApiServiceImpl>(); // <-- as 'type'
listenerBuilder.UseImplementation<ApiServiceImpl>(() => new ApiServiceImpl(...)); // <-- as 'factory function'
listenerBuilder.UseImplementation<ApiServiceImpl>(provider => new ApiServiceImpl(...)); // <-- as 'factory function with dependency injection'
})
...
Information
When
IServiceRemotingMessageSerializationProvider
is configured 'as type' all its parameters are automatically resolved using dependency injection.
The configuration starts using DefineGenericListener(...)
method:
new HostBuilder()
.DefineStatefulService(
serviceBuilder =>
{
serviceBuilder.DefineGenericListener(listenerBuilder => { ... });
})
.Build()
.Run()
You can configure what implementation of ICommunicationListener will be used by the infrastructure when creating ServiceInstanceListener or ServiceReplicaListener.
This is done by specifying a ICommunicationListener
factory function:
...
.DefineStatefulService(
serviceBuilder =>
{
serviceBuilder.DefineGenericListener(
listenerBuilder =>
{
listener.UseCommunicationListener(
(context, name, provider) =>
{
return /*ICommunicationListener*/;
}
)
});
})
.Build()
...
The factory function receives an instance of ServiceContext
in context
, name of the endpoint specified in UseEndpoint(...)
in name
and instance of IServiceProvider
in provider
that has access to all listener level dependencies.