-
SignalR Redis Backplane프로그래밍 2024. 10. 16. 12:57
닷넷 웹 개발에서 실시간 양방향 통신을 위한 설루션으로 가장 많이 채택하는 것이 SignalR일 것이다.
SignalR은 2013년 처음 오픈 소스로 처음 출시된 이후로 다양한 분야에 사용해 보았다.
채팅, 이미지 공유, 화면 공유 등 실시간으로 상대방과 통신하는 많은 분야에 사용할 수 있다.
이 영역에 web rtc도 있고 web rtc는 P2P에 가깝다.
SignalR은 web socket 프로토콜의 구현이다.
따라서, signalr을 사용하기 시작한 시점부터 웹 서버는 web socket을 사용하고 있다.
클라이언트 측은 명시적 선언을 하지 않는 이상 기본적으로 web socket으로 동작하도록 되어 있다.
물론, long polling, sse 등도 지원한다.
web socket의 절차에 따라 구현 메서드가 있는데 아래와 같다.
OnConnected
OnDisconnected
만약 Authorization Bearer Token을 헤더에 사용한다면 OnConnected 시점에 사용자 접속 정보를 확인할 수 있다.
또한 OnDisconnected 시점에 헤더 정보가 유지되므로 누가 접속이 끊겼는지도 알 수 있다.
따라서, 접속자의 상태관리, 즉, 접속 유무를 판단할 수 있는 정보를 기본적으로 알 수 있다.
이에 따라 signalr 구현을 한다면 Authorization Bearer Token등의 정보를 헤더에 설정한다면 유용하다.
signalr은 web socket 동작과 마찬가지로 최초 통신에서 연결정보를 확인하고 클라이언트와 서버의 전용 통신 pipeline을 생성해서 이후부터는 http통신이 아닌 스트리밍 통신을 하게 된다.
이에 최초 연결을 맺을 때만 http 통신을 한다는 것에 유의하자.
당신이 하나의 전용 서버로만 개발 및 운영한다면 특별한 설정없이 진행할 수 있을 것이다.
만약, 당신이 다수의 서버를 운영한다면 서버간에 서로 다른 사용자가 접속하고 같은 서버에 있지 않은 사용자는 서로 통신할 수 없을 것이다.
따라서, 서버간 사용자가 서로 연결되어 있어야 하는데 signalr에서는 이를 위해 redis를 backplane으로 지원한다.
그림으로 보면 아래와 같다.
server #1, server #2에 접속한 서로 다른 사용자의 통신을 위해 모든 client의 send method는 서버 측에 도달한 후 signalr의 redis backplane 설정에 따라 redis의 pub/sub을 사용하게 된다.
따라서, signalr의 hub에 구현된 method가 실행될 때 send method에 따라 즉시 실행되지 않고 redis를 통해 실행되게 된다.
아래의 코드를 보자
builder.Services.AddSignalR() .AddHubOptions<MeasurementHub>(options => { //1024 * 32; // 32KB //1024 * 1024 // 1MB options.MaximumReceiveMessageSize = 1024 * 32; //default })
위와 같이 설정할 경우 서버 자체내에서 실행되게 된다.
builder.Services.AddSignalR() .AddHubOptions<MeasurementHub>(options => { //1024 * 32; // 32KB //1024 * 1024 // 1MB options.MaximumReceiveMessageSize = 1024 * 32; //default }) .AddStackExchangeRedis(options => { options.ConnectionFactory = async writer => { var config = new ConfigurationOptions { AbortOnConnectFail = false }; var ip = Environment.GetEnvironmentVariable("REDIS_IP"); var port = Environment.GetEnvironmentVariable("REDIS_PORT"); config.EndPoints.Add(ip, port.xValue<int>()); config.SetDefaultPorts(); var connection = await ConnectionMultiplexer.ConnectAsync(config, writer); connection.ConnectionFailed += (_, e) => { Console.WriteLine("Connection to Redis failed."); }; if (!connection.IsConnected) { Console.WriteLine("Did not connect to Redis."); } return connection; }; })
위와 같이 설정할 경우 redis를 통해서 실행되게 된다.
클라우드 업체에서는 이러한 사항을 만족하기 위해 아래와 같이 제공한다.
AWS : Elastic Cache
AZURE : AZURE Service Bus
GCP : Memorystore for Redis
도움이 되길 바라며
'프로그래밍' 카테고리의 다른 글
ASP.NET CORE Serilog 설정 및 사용 (0) 2024.10.17 ASP.NET CORE에서의 JWT 처리 (0) 2024.10.16 EF CORE의 상태 변경 (1) 2024.10.16 예약, 예매 시스템에 대한 고찰-2 (6) 2024.10.16 Entity Framework는 Unit of Work가 필요한가? (0) 2024.10.14