-
Notifications
You must be signed in to change notification settings - Fork 9.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SignalR and WebSocket API in Amazon API Gateway #9522
Comments
How would you like to use SignalR in the amazon API gateway? From a cursory glance it looks as though the websocket gateway is a very specific protocol plus a very specific way to route messages. I haven't looked deeply enough but I don't see any obvious integration, at least not without significantly changing either side of the equation (how signalr works or how the websocket gate way works). cc @normj for any ideas |
Hi David, Thank you for the response. Yes I have already raised this with Norm. So how does the SignalR Service communicate with a separate ASP.Net app? Does it open a local WebSocket between the service and the app, so the app is unaware who it is talking to? Yes I understand that in the WebSocket API in Amazon API Gateway, the incoming WebSocket request is turned into a JSON event with a connection Id. So the receiving app just receives an event. What I was hoping was that I could internally route this incoming and outgoing API connection Id to SignalR so I could use the framework. From your last SignalR presentation, it looked like the layers were more conducive to different protocols,package types and communication alternatives. Regards, Dave |
Yes, the SignalR service acts like a websocket proxy. All of the protocol parsing is handled in the framework itself, the service just handles the websocket traffic and fowards those bytes to the application over a different transport (see https://github.com/Azure/azure-signalr/blob/dev/docs/internal.md for more details). As far as SignalR is concerned, it's running on top of a different transport; instead of bytes coming from a client, it's coming from the a multiplexed websocket connection.
Right, it's JSON in a specific format so that it can be routed. Essentially, thats required data as part of using the amazon service to even function it seems.
Maybe but I'm not connecting the dots, SignalR is flexible and has 2 built in protocols (even some 3rd party ones) and you can plug in your own but its possible you'd need to replace protocols on both sides to have a chance at this working. Is there a way to forward the websocket traffic from the client to a backend application? |
So looking at https://github.com/eByte23/Amazon.Lambda.SignalR it seems like it might be possible: It seems like the interaction with the backend is over http? I could be reading it wrong but it looks like you need to handle incoming HTTP request and basically build a transport on top of that. Then to response, possibly you're given a callback URL to send data to when you want to respond. This seems extremely inefficient (especially if you can only respond a connection at a time) but maybe it works fine for smaller workloads (or maybe there are capabilities I'm missing) |
I originally built my project using MassTransit which provides a backplane for broadcasting events distributed across multiples servers/nodes. https://masstransit-project.com/advanced/signalr/ I began migrating to api gateway using the web socket integration with little luck. From what I'm reading in this thread it seems to me a better option would be to use the standard http api gateway alongside mass transit for the backplane. Before I migrated to aws api gateway I was also using Ocelot which is a .NET core API gateway since my plan was to run containers at that time not serverless. Ocelot has a load balancer for signal r build right into it. Instead of using api gateway could I use a load balancer lambda integration. Would that function properly across multiples nodes? |
I think for the time being it is much easier to just abandon SignalR when using the AWS API Gateway. I've come up with this boilerplate code that connects, and disconnects using the api gateway. Its based on the work done here: https://github.com/normj/netcore-simple-websockets-chat-app and inside the aws aspnetcore server package itself. using Microsoft.AspNetCore.Hosting;
using Amazon.Lambda.AspNetCoreServer;
using Microsoft.AspNetCore.Http.Features;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using Newtonsoft.Json;
using Serilog;
using System.Threading.Tasks;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Reflection;
using System;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
namespace Chat
{
public class Handler
{
public APIGatewayProxyResponse FunctionHandlerAsync(APIGatewayProxyRequest apiGatewayRequest, ILambdaContext lambdaContext)
{
Start();
lambdaContext.Logger.LogLine("CONTEXT: " + JsonConvert.SerializeObject(lambdaContext));
lambdaContext.Logger.LogLine("REQUEST: " + JsonConvert.SerializeObject(apiGatewayRequest));
if(apiGatewayRequest.RequestContext.EventType == "CONNECT")
{
lambdaContext.Logger.LogLine($"We have been connected to the websocket! Connection Id = {apiGatewayRequest.RequestContext.ConnectionId}");
} else if(apiGatewayRequest.RequestContext.EventType == "DISCONNECT")
{
lambdaContext.Logger.LogLine($"We have been disconnected from the websocket! Connection Id = {apiGatewayRequest.RequestContext.ConnectionId}");
} else
{
lambdaContext.Logger.LogLine($"unknown event in web socket. Connection Id = {apiGatewayRequest.RequestContext.ConnectionId}");
}
return new APIGatewayProxyResponse
{
StatusCode = 200,
Body = "Connected."
};
}
protected void Start()
{
var builder = CreateWebHostBuilder();
Init(builder);
}
protected void Init(IWebHostBuilder builder)
{
builder
.UseSerilog((context, loggerConfiguration) =>
{
loggerConfiguration.ReadFrom.Configuration(context.Configuration);
}, true, false);
//.UseStartup<Startup>();
}
protected virtual IWebHostBuilder CreateWebHostBuilder()
{
var builder = new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
if (env.IsDevelopment())
{
var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
if (appAssembly != null)
{
config.AddUserSecrets(appAssembly, optional: true);
}
}
config.AddEnvironmentVariables();
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("LAMBDA_TASK_ROOT")))
{
logging.AddConsole();
logging.AddDebug();
}
else
{
logging.AddLambdaLogger(hostingContext.Configuration, "Logging");
}
})
.UseDefaultServiceProvider((hostingContext, options) =>
{
options.ValidateScopes = hostingContext.HostingEnvironment.IsDevelopment();
});
return builder;
}
}
} |
Sounds good! |
Thank you for contacting us. Due to a lack of activity on this discussion issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue. This issue will be locked after 30 more days of inactivity. If you still wish to discuss this subject after then, please create a new issue! |
Is your feature request related to a problem? Please describe.
In WebSocket API in Amazon API Gateway, the Gateway handles the websocket $connect, $disconnect and routing. This is a similar idea to the SignalR service and allows load spreading.
Describe the solution you'd like
I would like to be able to use SignalR with the WebSocket API in Amazon API Gateway using ASP.Net Web application running in AWS Lambda
Describe alternatives you've considered
We can use SignalR via HTTP in a single AWS Lambda function but it will not load balance. Because the $connect, $disconnect and message are handled by the Websocket API Gateway, we need a way to be able to route these calls to the appropriate hub for handling.
Additional context
DotNet Core on AWS Lambda is a major piece for us and others. Handling SignalR just on Azure using the SignalR Service is counter to the culture of openness and SignalR on AWS Lambda should get equal consideration. Please offer us a way to use SignalR in the AWS environment.
The text was updated successfully, but these errors were encountered: