Azure Function with Event Hub Trigger - Can I change the Port Used to Retrieve Events?

Viewed 514

My Azure function successfully retrieves eventhub events on a home network, but not from inside my company network. Error received as follows:

A connection attempt failed because the connected party did not properly respond >after a period of time, or established connection failed because connected host >has failed to respond

By default, the eventhub trigger uses AMQ protocol, which is blocked by our firewall. I'd like to change the transport type to use https over port 443.

Code generated by Visual Studio 2022 (works fine from home network)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.EventHubs;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;

namespace EventHubConsumers
{
    public class Function1
    {
        [FunctionName("Function1")]
        public async Task Run([EventHubTrigger("test1", Connection = "ConnectionToEventHubReceived")] EventData[] events, ILogger log)
       
        {
            var exceptions = new List<Exception>();
            foreach (EventData eventData in events)
            {
                try
                {
                    string messageBody = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count);

                    // Replace these two lines with your processing logic.
                    log.LogInformation($"C# Event Hub trigger function processed a message: {messageBody}");
                    await Task.Yield();
                }
                catch (Exception e)
                {
                    // We need to keep processing the rest of the batch - capture this exception and continue.
                    // Also, consider capturing details of the message that failed processing so it can be processed again later.
                    exceptions.Add(e);
                }
            }

            // Once processing of the batch is complete, if any messages in the batch failed processing throw an exception so that there is a record of the failure.
            if (exceptions.Count > 1)
                throw new AggregateException(exceptions);
            if (exceptions.Count == 1)
                throw exceptions.Single();
        }
    }
}

How can I change the transport type? Thanks in advance!

2 Answers

To use port 443, you'll need to change the transport option to AmqpWebSockets.

Update

The option to set the transport type is available as part of the host settings for Microsoft.Azure.WebJobs.Extensions.EventHubs v5.0 and above; the documentation was outdated.

Transport-related settings can be specified using:

{
  "extensions": {
    "eventHubs": {
      "transportType" : "amqpWebSockets",
      "webProxy" : "https://proxyserver:8080",
      "customEndpointAddress" : "amqps://company.gateway.local"            
  }
}
  

These should appear in the settings documentation in the near future. Until then, details about them can be found in the EventHubOptions docs.

Original Answer (valid, but requires more effort)

Unfortunately, this is not exposed in the settings. You'll need to create a startup class for the Function, if you don't already have one, and configure DI to set the transport option when creating Event Hubs clients.

For example, a minimal implementation would look something like:

[assembly: FunctionsStartup(typeof(SomeNamespace.Startup))]

namespace SomeNamespace
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            var wjBuilder = builder.Services.AddWebJobs(_ => {});

            // This method allows you to mutate the options used to 
            // create the Event Hubs clients and set the transport.
            builder.AddEventHubs(options =>
            {
                options.TransportType = EventHubsTransportType.AmqpWebSockets;
            });  

            wjBuilder.AddBuiltInBindings();
            wjBuilder.AddExecutionContextBinding();
        }
    }
}

Getting events from an EventHub via Azure functions and HTTPS can also be solved with a Timer Trigger and the EventHubConsumerClient. Note the options passed into its constructor to configure it for AmqpWebSockets.

using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using System.Text;
using System.Threading.Tasks;
using Azure.Messaging.EventHubs;
using Azure.Messaging.EventHubs.Consumer;

namespace EventHubConsumerPOC
{
    public class Function1
    {

        private const string connectionStringTest1 = "Endpoint=sb://[[ REDACTED ]].servicebus.windows.net/;SharedAccessKeyName=[[ REDACTED ]];SharedAccessKey=[[ REDACTED ]];EntityPath=[[ REDACTED ]]";
        private const string eventHubName1 = "[[ REDACTED ]]";
        private const string consumerGroup = "$Default";

        [FunctionName("Function1")]
        public async Task RunAsync([TimerTrigger("0 * * * * *")] TimerInfo myTimer, ILogger log)  //every 1 minute
        {
            log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");

            await GetTask(log);

        }

        private async Task GetTask(ILogger log)
        {
            var processorOptions = new EventHubConsumerClientOptions
            {
                ConnectionOptions = new EventHubConnectionOptions
                {
                    TransportType = EventHubsTransportType.AmqpWebSockets
                }
            };
            var consumerClient = new EventHubConsumerClient(consumerGroup, connectionStringTest1, processorOptions);

            await foreach (PartitionEvent _event in consumerClient.ReadEventsAsync())
            {
                log.LogInformation(Encoding.UTF8.GetString(_event.Data.EventBody));
            }
        }
    }
}```
Related