Host NServiceBus endpoints with Azure Functions and Azure Service Bus triggers.
Basic usage
Endpoint configuration
static readonly IFunctionEndpoint endpoint = new FunctionEndpoint(executionContext =>
{
var serviceBusTriggeredEndpointConfiguration = ServiceBusTriggeredEndpointConfiguration.FromAttributes();
// customize configuration here
return serviceBusTriggeredEndpointConfiguration;
});
The endpoint is automatically configured with the endpoint name and the transport connection string based on the values defined in the [ServiceBusTrigger]
attribute using the ServiceBusTriggeredEndpointConfiguration.
method.
Alternatively, the endpoint name can be passed in manually:
static readonly IFunctionEndpoint endpoint = new FunctionEndpoint(executionContext =>
{
var serviceBusTriggeredEndpointConfiguration = new ServiceBusTriggeredEndpointConfiguration("ASBTriggerQueue");
return serviceBusTriggeredEndpointConfiguration;
});
Azure Function definition
Pass the incoming message to the NServiceBus endpoint:
[FunctionName("ASBTriggerQueue")]
public static async Task Run(
[ServiceBusTrigger(queueName: "ASBTriggerQueue")]
Message message,
ILogger logger,
ExecutionContext executionContext)
{
await endpoint.Process(message, executionContext, logger);
}
NServiceBus interacts directly with the Azure Functions logging infrastructure by passing the ILogger
instance from the function parameters to the endpoint's Process
method.
Dispatching outside a message handler
Messages can be dispatched outside a message handler in functions activated by queue- and non-queue-based triggers.
[FunctionName("HttpSender")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest request, ExecutionContext executionContext, ILogger logger)
{
logger.LogInformation("C# HTTP trigger function received a request.");
var sendOptions = new SendOptions();
sendOptions.SetDestination("DestinationEndpointName");
await functionEndpoint.Send(new TriggerMessage(), sendOptions, executionContext, logger);
return new OkObjectResult($"{nameof(TriggerMessage)} sent.");
}
private static readonly IFunctionEndpoint functionEndpoint = new FunctionEndpoint(executionContext =>
{
var configuration = new ServiceBusTriggeredEndpointConfiguration("HttpSender");
configuration.AdvancedConfiguration.SendOnly();
return configuration;
});
IFunctionsHostBuilder usage
As an alternative to the configuration approach described in the previous section, an endpoint can also be configured with a static IFunctionEndpoint
field using the IFunctionsHostBuilder
API as described in Use dependency injection in .NET Azure Functions.
Endpoint configuration
NServiceBus can be registered and configured on the host builder using the UseNServiceBus
extension method in the startup class:
class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.UseNServiceBus(() => new ServiceBusTriggeredEndpointConfiguration("MyFunctionsEndpoint"));
}
}
Any services registered via the IFunctionsHostBuilder
will be available to message handlers via dependency injection. The startup class must be declared via the FunctionStartup
attribute: [assembly: FunctionsStartup(typeof(Startup))]
.
Azure Function definition
To access IFunctionEndpoint
from the Azure Function trigger, inject the IFunctionEndpoint
via constructor-injection into the containing class:
class MyFunction
{
readonly IFunctionEndpoint endpoint;
// inject the FunctionEndpoint via dependency injection:
public MyFunction(IFunctionEndpoint endpoint)
{
this.endpoint = endpoint;
}
[FunctionName("MyFunctionsEndpoint")]
public async Task Run(
[ServiceBusTrigger(queueName: "MyFunctionsEndpoint")]
Message message,
ILogger logger,
ExecutionContext executionContext)
{
await endpoint.Process(message, executionContext, logger);
}
}
Dispatching outside a message handler
Triggering a message using HTTP function:
public class HttpSender
{
readonly IFunctionEndpoint functionEndpoint;
public HttpSender(IFunctionEndpoint functionEndpoint)
{
this.functionEndpoint = functionEndpoint;
}
[FunctionName("HttpSender")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest request, ExecutionContext executionContext, ILogger logger)
{
logger.LogInformation("C# HTTP trigger function received a request.");
var sendOptions = new SendOptions();
sendOptions.RouteToThisEndpoint();
await functionEndpoint.Send(new TriggerMessage(), sendOptions, executionContext, logger);
return new OkObjectResult($"{nameof(TriggerMessage)} sent.");
}
}
Configuration
License
The license is provided via the NSERVICEBUS_LICENSE
environment variable, which is set via the Function settings in the Azure Portal. For local development, use local.
. In Azure, specify a Function setting using the environment variable as the key.
{
"IsEncrypted": false,
"Values": {
...
"NSERVICEBUS_LICENSE": "<?xml version=\"1.0\" encoding=\"utf-8\"?><license id=\"1222e1d1-2222-4a46-b1c6-943c442ca710\" expiration=\"2113-11-30T00:00:00.0000000\" type=\"Standard\" LicenseType=\"Standard\" LicenseVersion=\"4.0\" MaxMessageThroughputPerSecond=\"Max\" WorkerThreads=\"Max\" AllowedNumberOfWorkerNodes=\"Max\">. . .</license>"
}
}
Custom diagnostics
NServiceBus startup diagnostics are disabled by default when using Azure Functions. Diagnostics can be written to the logs via the following snippet:
serviceBusTriggeredEndpointConfiguration.LogDiagnostics();
Error queue
For recoverability to move the continuously failing messages to the error queue rather than to the Azure Service Bus dead-letter queue, the error queue must be created in advance and configured using the following API:
serviceBusTriggeredEndpointConfiguration.AdvancedConfiguration.SendFailedMessagesTo("error");
Known constraints and limitations
When using Azure Functions with Azure Service Bus (ASB) the following points must be taken into consideration:
- There is no support for the
SendsAtomicWithReceive
transport transaction mode. - The Configuration API exposes NServiceBus transport configuration options via the
configuration.
method to allow customization; however, not all of the options will be applicable to execution within Azure Functions.Transport
Preparing the Azure Service Bus namespace
Function endpoints cannot create their own queues or other infrastructure in the Azure Service Bus namespace.
Use the asb-transport
command line (CLI) tool to provision the entities in the namespace for the Function endpoint.
Creating the endpoint queue
asb-transport endpoint create <queue name>
See the full documentation for the asb-transport endpoint create
command for more details.
asb-tranport
command-line tool is not used to create the queue, it is recommended to set the MaxDeliveryCount
setting to the maximum value.Subscribing to events
asb-transport endpoint subscribe <queue name> <eventtype>
See the full documentation for the asb-transport endpoint subscribe
command for more details.