Redis backplane cho ASP.NET Core SignalR scale-out
Bởi Andrew Stanton-Nurse, Brady Gaster và Tom Dykstra
Bài viết này giải thích các khía cạnh dành riêng cho SignalR khi thiết lập máy chủ Redis để sử dụng cho việc scale out (mở rộng theo chiều ngang) ứng dụng ASP.NET Core SignalR.
Cảnh báo: Bài viết này hiển thị việc sử dụng chuỗi kết nối (connection strings). Khi sử dụng cơ sở dữ liệu cục bộ để phát triển và kiểm thử, không cần xác thực người dùng cơ sở dữ liệu qua chuỗi kết nối. Trong môi trường production, chuỗi kết nối đôi khi bao gồm mật khẩu để xác thực truy cập cơ sở dữ liệu. Thông tin xác thực mật khẩu (ROPC) trong chuỗi kết nối là rủi ro bảo mật nên tránh trong ứng dụng production. Ứng dụng production nên sử dụng luồng xác thực an toàn nhất có sẵn.
Thiết lập Redis backplane
- Triển khai máy chủ Redis.
> Quan trọng: Để sử dụng trong production, Redis backplane chỉ được khuyến nghị khi nó chạy trong cùng trung tâm dữ liệu với ứng dụng SignalR. Nếu không, độ trễ mạng sẽ làm giảm hiệu suất. Nếu ứng dụng SignalR của bạn đang chạy trên đám mây Azure, chúng tôi khuyến nghị sử dụng Azure SignalR Service thay vì Redis backplane. > > Để biết thêm thông tin, xem các tài nguyên sau: > > - ASP.NET Core SignalR production hosting and scaling > - Tài liệu Redis > - Tài liệu Azure Redis Cache
- Trong ứng dụng SignalR, cài đặt gói NuGet sau:
Microsoft.AspNetCore.SignalR.StackExchangeRedis- Gọi AddStackExchangeRedis bằng cách thêm dòng sau trước dòng gọi
builder.Build()) trong tệpProgram.cs.
``csharp builder.Services.AddSignalR().AddStackExchangeRedis("<your_Redis_connection_string>"); ``
- Cấu hình các tùy chọn khi cần:
Hầu hết các tùy chọn có thể được đặt trong chuỗi kết nối hoặc trong đối tượng ConfigurationOptions. Các tùy chọn được chỉ định trong ConfigurationOptions sẽ ghi đè các tùy chọn được đặt trong chuỗi kết nối.
Ví dụ sau cho thấy cách đặt các tùy chọn trong đối tượng ConfigurationOptions. Ví dụ này thêm channel prefix (tiền tố kênh) để nhiều ứng dụng có thể chia sẻ cùng một phiên bản Redis, như được giải thích trong bước tiếp theo.
``csharp builder.Services.AddSignalR() .AddStackExchangeRedis(connectionString, options => { options.Configuration.ChannelPrefix = RedisChannel.Literal("MyApp"); }); ``
Trong code trên, options.Configuration được khởi tạo với bất kỳ thứ gì được chỉ định trong chuỗi kết nối.
Để biết thông tin về các tùy chọn Redis, xem tài liệu StackExchange Redis.
- Nếu bạn đang sử dụng một máy chủ Redis cho nhiều ứng dụng SignalR, hãy sử dụng channel prefix khác nhau cho mỗi ứng dụng SignalR.
Đặt channel prefix giúp cô lập một ứng dụng SignalR với các ứng dụng khác sử dụng channel prefix khác nhau. Nếu bạn không gán các prefix khác nhau, một tin nhắn được gửi từ một ứng dụng đến tất cả client của nó sẽ đến tất cả client của tất cả các ứng dụng sử dụng máy chủ Redis làm backplane.
- Cấu hình phần mềm load balancing (cân bằng tải) của server farm cho sticky sessions. Dưới đây là một số ví dụ về tài liệu hướng dẫn:
- IIS
- HAProxy
- Nginx
Lỗi máy chủ Redis
Khi máy chủ Redis ngừng hoạt động, SignalR ném các ngoại lệ (exceptions) cho biết tin nhắn sẽ không được gửi. Một số thông báo ngoại lệ điển hình:
- Failed writing message
- Failed to invoke hub method 'MethodName'
- Connection to Redis failed
SignalR không lưu vào buffer tin nhắn để gửi chúng khi máy chủ hoạt động trở lại. Bất kỳ tin nhắn nào được gửi trong khi máy chủ Redis ngừng hoạt động đều bị mất.
SignalR tự động kết nối lại khi máy chủ Redis khả dụng trở lại.
Hành vi tùy chỉnh khi kết nối thất bại
Đây là ví dụ cho thấy cách xử lý các sự kiện thất bại kết nối Redis.
services.AddSignalR()
.AddMessagePackProtocol()
.AddStackExchangeRedis(o =>
{
o.ConnectionFactory = async writer =>
{
var config = new ConfigurationOptions
{
AbortOnConnectFail = false
};
config.EndPoints.Add(IPAddress.Loopback, 0);
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 Cluster (Cụm Redis)
Redis Cluster sử dụng nhiều máy chủ Redis hoạt động đồng thời để đạt được tính khả dụng cao. Khi Redis Cluster được sử dụng làm backplane cho SignalR, tin nhắn được gửi đến tất cả các node của cluster mà không cần sửa đổi code trong ứng dụng.
Có sự đánh đổi giữa số lượng node trong cluster và thông lượng của backplane. Tăng số lượng node làm tăng tính khả dụng của cluster nhưng làm giảm thông lượng vì tin nhắn phải được truyền đến tất cả các node trong cluster.
Trong ứng dụng SignalR, bao gồm tất cả các node Redis có thể bằng một trong các cách sau:
- Liệt kê các node trong chuỗi kết nối được phân cách bằng dấu phẩy.
- Nếu sử dụng hành vi tùy chỉnh cho các lỗi kết nối, thêm các node vào
ConfigurationOptions.Endpoints.