Я запускаю службы с помощью docker-compose, и все контейнеры включены. та же сеть, которая соединена мостом с хостом.
Конфигурация для nginx выглядит так:
Код: Выделить всё
server {
listen 80;
server_name example.com *.example.com;
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name example.com *.example.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://docker-service-name:5000;
proxy_redirect off;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $server_name;
}
}
Код: Выделить всё
ENV ASPNETCORE_URLS=http://+:5000
Теперь я решил добавить собственный Концентратор SignalR, который может уведомлять клиентов об обновлениях, которые делает другой клиент, чтобы обеспечить более динамичную и плавную работу.
SignalR загружается следующим образом в Program.cs:
Код: Выделить всё
builder.Services.AddSignalR();
builder.Services.AddResponseCompression(opts =>
{
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
["application/octet-stream"]);
});
app.UseResponseCompression();
app.MapHub(NotificationHub.HubUrl);
Код: Выделить всё
public class NotificationHub : Hub
{
public const string HubUrl = "/notifications";
public const string InviteCreatedMethod = "InviteCreated";
public const string InviteAcceptedMethod = "InviteAccepted";
private static readonly ILogger Log = Serilog.Log.ForContext();
public override Task OnConnectedAsync()
{
Log.Debug("{ConnectionId} connected", Context.ConnectionId);
return base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? e)
{
Log.Debug(e, "{ConnectionId} disconnected", Context.ConnectionId);
await base.OnDisconnectedAsync(e);
}
}
public interface INotificationClient
{
Task InviteCreated(InviteCreatedNotification notification);
Task InviteAccepted(InviteAcceptedNotification notification);
}
Код: Выделить всё
@implements IAsyncDisposable
@code {
private HubConnection _hubConnection;
public async ValueTask DisposeAsync()
{
Log.Debug("Page {Page} disposing", nameof(Home));
await _hubConnection.DisposeAsync();
}
protected override async Task OnInitializedAsync()
{
Log.Debug("Page {Page} initialized", nameof(Home));
_hubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri(NotificationHub.HubUrl))
.Build();
_hubConnection.On(NotificationHub.InviteCreatedMethod, HandleInviteCreated);
_hubConnection.On(NotificationHub.InviteAcceptedMethod, HandleInviteAccepted);
await _hubConnection.StartAsync();
}
private void HandleInviteCreated(InviteCreatedNotification notification)
{
Log.Debug("{Notification} received", nameof(InviteCreatedNotification));
}
private void HandleInviteAccepted(InviteAcceptedNotification notification)
{
Log.Debug("{Notification} received", nameof(InviteAcceptedNotification));
}
}
При локальной работе я вижу, что получаю запросы на URL-адрес /notifications:
Код: Выделить всё
[14:09:11 INF] Request starting HTTP/2 POST https://localhost:7108/notifications/negotiate?negotiateVersion=1 - null 0
[14:09:11 INF] Executing endpoint '/notifications/negotiate'
Когда время ожидания nginx истекает, это то, что зарегистрирован:
Код: Выделить всё
2024/12/18 15:10:36 [error] 39#39: *1 upstream timed out (110: Operation timed out) while reading response header from upstream, client: [client public IP], server: example.com, request: "GET / HTTP/1.1", upstream: "http://172.19.0.7:5000/", host: "www.example.com"
Код: Выделить всё
[15:09:36 INF] Request starting HTTP/1.1 GET http://www.example.com/ - null null
[15:09:36 INF] Executed DbCommand (2ms) [Parameters=[@__p_0='?' (DbType = Int64)], CommandType='Text', CommandTimeout='30']
SELECT a."Id", a."AccessFailedCount", a."ConcurrencyStamp", a."Email", a."EmailConfirmed", a."LockoutEnabled", a."LockoutEnd", a."NormalizedEmail", a."NormalizedUserName", a."PasswordHash", a."PhoneNumber", a."PhoneNumberConfirmed", a."SecurityStamp", a."TwoFactorEnabled", a."UserName"
FROM "AspNetUsers" AS a
WHERE a."Id" = @__p_0
LIMIT 1
[15:09:36 INF] Executed DbCommand (1ms) [Parameters=[@__user_Id_0='?' (DbType = Int64)], CommandType='Text', CommandTimeout='30']
SELECT a."Id", a."ClaimType", a."ClaimValue", a."UserId"
FROM "AspNetUserClaims" AS a
WHERE a."UserId" = @__user_Id_0
[15:09:36 INF] Executing endpoint '/ (/)'
[15:09:36 DBG] Adding entry for 18b0d7e3-dde7-45b6-875b-efb27271616c/MudBlazor.MudPopoverProvider. 1 total observers after add.
[15:09:36 DBG] Updating entry for 18b0d7e3-dde7-45b6-875b-efb27271616c/MudBlazor.MudPopoverProvider. 1 total observers.
[15:09:36 DBG] Page Home initialized
Что я пробовал:
- Обновите конфигурацию nginx в соответствии с рекомендациями Microsoft по использованию nginx вместе с ASP.NET.
Код: Выделить всё
map $http_connection $connection_upgrade {
"~*Upgrade" $http_connection;
default keep-alive;
}
location / {
proxy_pass http://docker-service-name:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
- Явная настройка местоположения для URL-адреса концентратора, как предложено в ответе здесь на SO. Я добавил его как второе место после существующего "/".
Код: Выделить всё
location /notifications {
proxy_pass http://docker-service-name:5000;
# Configure WebSockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_cache_bypass $http_upgrade;
# Configure ServerSentEvents
proxy_buffering off;
# Configure LongPolling
proxy_read_timeout 100s;
proxy_set_header Host $host;
}
- Обновите конфигурацию nginx в соответствии с рекомендациями Microsoft по использованию nginx вместе с SignalR.
Код: Выделить всё
server {
listen 443 ssl;
server_name example.com *.example.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://docker-service-name:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /notifications {
proxy_pass http://docker-service-name:5000;
# Configuration for WebSockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_cache off;
proxy_http_version 1.1;
# Configuration for ServerSentEvents
proxy_buffering off;
# Configuration for LongPolling or if your KeepAliveInterval is longer than 60 seconds
proxy_read_timeout 100s;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Как можно ли настроить nginx в качестве обратного прокси-сервера перед серверным приложением Blazor, использующим SignalR?
Подробнее здесь: https://stackoverflow.com/questions/792 ... ignalr-hub