Closed domenichelfenstein closed 4 years ago
Still no response...
Is it simply not possible, or is this just the wrong place for asking this question? If the latter is the case, what would be the right place?
Sorry I couldn't understand your request and would you explain a bit more?
Do you want to use SignalR between client and service or clients, what's Redis used in the function?
Besides, SignalR requires to negotiation before send messages. And simply AddSignalR() without UseSignalR() or UseEndpoints()(after AspNetCore3.0) won't real work with SignalR. Not able to saw your complete code and couldn't know the blocking part. You may take a look at our sample for some reference first: https://github.com/Azure/azure-functions-signalrservice-extension/blob/dev/samples/simple-chat/csharp/FunctionApp/Functions.cs.
Hi @JialinXin Thank you for your response.
Our scenario: Until now, we had 2 App Services and an Angular Client. The client only speaks with Service A, which also contains a SignalR endpoint. Service B exists only for background work (long-running calculations and/or processing ServiceBus messages). After the completion of such messages, the background-working service sometimes wants to inform the client about the new state of the system. Right now, it does that via the Redis backplane (both services A and B are attached to the same Redis backplane for SignalR, but only service A provides a SignalR endpoint to the client). This all works for now. But we intended to refactor service B (the background-worker) to Azure Functions for scalability and cost reasons.
I took a look at your sample and what I want to have in the end is a function like this (I just copied the sample):
[FunctionName("broadcast")]
public static async Task Broadcast(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")]HttpRequest req,
[SignalR(HubName = "simplechat")]IAsyncCollector<SignalRMessage> signalRMessages)
{
var message = new JsonSerializer().Deserialize<ChatMessage>(new JsonTextReader(new StreamReader(req.Body)));
var serviceHubContext = await StaticServiceHubContextStore.Get().GetAsync("simplechat");
await serviceHubContext.Clients.All.SendAsync("newMessage", message);
}
The question is, how can I make this sample work with Redis instead of Azure SignalR Service as the backplane. (https://docs.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-3.1#redis-backplane) (https://docs.microsoft.com/en-us/aspnet/core/signalr/redis-backplane?view=aspnetcore-2.1)
Thanks in advance for your help
You don’t need to when using the service. The service itself is the backplane in this case
You don’t need to when using the service. The service itself is the backplane in this case
Yes, I know that. But what if I want to use Redis instead of the Azure SignalR Service?
It seems like the whole Redis as backplane idea has been declared obsolete by MS. Is this true?
So you'd like to make ServiceB publish the message to both Azure SignalR Service and Redis in the function to ensure it could be received by ServiceA? We don't support build-in Redis backplane like that in azure function now, though inside our service we have some strategy to ensure message transfer. Probably you'd just do the backplane publish inside the function like this:
private static IConnectionMultiplexer _redisConnectionMultiplexer =
ConnectionMultiplexer.Connect("<redis-connecion-string>");
[FunctionName("broadcast")]
public static async Task Broadcast(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")]HttpRequest req,
[SignalR(HubName = "simplechat")]IAsyncCollector<SignalRMessage> signalRMessages)
{
var message = new JsonSerializer().Deserialize<ChatMessage>(new JsonTextReader(new StreamReader(req.Body)));
var serviceHubContext = await StaticServiceHubContextStore.Get().GetAsync("simplechat");
await serviceHubContext.Clients.All.SendAsync("newMessage", message);
// with some check to determine send redis.
var db = _redisConnectionMultiplexer.GetDatabase();
db.StringSet("somekey", message);
}
So you'd like to make ServiceB publish the message to both Azure SignalR Service and Redis in the function to ensure it could be received by ServiceA?
I'm really starting to repeat myself: I want to use Redis as backplane instead of the Azure SignalR Service. I want to use SignalR without using the Azure SignalR Service.
I understand if you say this is not supported by your libraries (it was supported in ASP.NET core, but it maybe not with Azure Functions).
I'm really sorry if I can't express myself any better. English isn't my native language, as you might already have guessed...
I see, you’re trying to send to redis from an azure function. It might be possible today by using the original code you have if you inject the IHubContext\<YourHub> into your function class.
It doesn’t really have much to do with the severless version of azure signalr though.
Yes, that's what I'm trying to achieve.
Also, the injection of IHubContext<MyHub>
works for functions with ServiceBusTrigger
s. I can confirm that.*
However, as I said in my initial post, when I use my original code, all the HttpTrigger
functions don't work any longer because they suddenly start to respond with 401. This is because of the AddSignalR()
method, which seems to start a process that creates an Authorization-Check whenever a HttpTrigger
function is called.
* It would probably also work for all other functions with other kinds of triggers.
It's true; my problem has probably not much to do with the serverless version of azure signalr. It's more a problem of integrating plain old signalr with azure functions.
The question remains: How could I solve this, and if this is the wrong place for asking, what would be the right one?
which seems to start a process that creates an Authorization-Check whenever a HttpTrigger function is called.
I don't see how AddSignalR would cause a 401 in the HttpTrigger.
The question remains: How could I solve this, and if this is the wrong place for asking, what would be the right one?
It's fine to ask it here but it wasn't initially clear what you were doing since it was in the context of the Azure SignalR Service (which you aren't using).
cc @fabiocav for ideas on the 401.
@domenichelfenstein if you remove the call to AddSignalR, does your ping function work?
@domenichelfenstein if you remove the call to AddSignalR, does your ping function work?
Yes it does.
So far I was able to track the problem down to the service.AddConnections();
call which happens within AddSignalR()
. But then I couldn't dig any deeper because I don't have the sources of AddConnections()
and don't know where to find them...
Interesting, try calling AddSignalRCore instead of AddSignalR.
The source for AddConnections is here and it's likely this call to AddAuthorization https://github.com/dotnet/aspnetcore/blob/7669cf0d036cc0cb3b481aba49253cd35d85c633/src/SignalR/common/Http.Connections/src/ConnectionsDependencyInjectionExtensions.cs#L25
Yes, that's actually more than likely :)
I'm gonna give it a try. Thank you so much, you've already helped me a lot!
try calling AddSignalRCore instead of AddSignalR.
It still doesn't work, which isn't a huge surprise since it contains this line: https://github.com/dotnet/aspnetcore/blob/c84e37f30def9ff0b2d12e877e3de6c283be6145/src/SignalR/server/Core/src/SignalRDependencyInjectionExtensions.cs#L32
I'm asking myself if I should just copy the whole body of this method and remove the AddAuthorization()
line...
...which of course doesn't work, because many of the classes I would need are internal
:(
Yes, the implementations are internal. Lets move this to https://github.com/azure/azure-functions-host/issues
Sure! Shall I create a new issue over there?
I've tried to add SignalR with Redis as backplane as I would have when using a normal Azure App Service:
Then I set up the simplest HttpTrigger I could think of:
Unfortunately when I've tried calling then ping function I got a status code 401 response.
The thing is: We already have a Redis backplane and using it in other services. Now I wanted to be able to add notifications to the backplane, so that the other services can distribute the SignalR-Notifications to the clients.
How can I do that?