DOJ*_*Jay 4 microservices asp.net-core asp.net-core-signalr ocelot blazor-client-side
我正在尝试通过 Ocelot API 网关将 Blazor 客户端连接到简单微服务中的 SignalR 集线器。我对所有 ASP.NET Core 项目都使用 SSL。
网关在调用 https 端点时工作正常,当我直接从网关浏览器调用 signalR hub 端点(正确显示 Ocelot 路由)时,我收到“需要连接 ID”。
不幸的是,当我尝试从 blazor 客户端应用程序连接到集线器时,出现以下错误
失败:Ocelot.Errors.Middleware.ExceptionHandlerMiddleware[0] requestId:0HM4U0GLR9ACR:00000001,previousRequestId:没有以前的请求ID,消息:全局错误处理程序中捕获异常,异常消息:仅以“ws://”或“wss”开头的Uris支持 ://'。(参数'uri'),异常堆栈:在Ocelot.WebSockets.Middleware.WebSocketsProxyMiddleware.Proxy(HttpContext context,String serverEndpoint)在Ocelot.WebSockets.Middleware的System.Net.WebSockets.ClientWebSocket.ConnectAsync(Uri uri,CancellationToken CancellationToken) .WebSocketsProxyMiddleware.Invoke(HttpContext httpContext) 在 Microsoft.AspNetCore.MiddlewareAnalysis.AnalysisMiddleware.Invoke(HttpContext httpContext) 在 Ocelot.DownstreamUrlCreator.Middleware.DownstreamUrlCreatorMiddleware.Invoke(HttpContext httpContext) 在 Microsoft.AspNetCore.MiddlewareAnalysis.AnalysisMiddleware.Invoke(HttpContext httpContext)在 Ocelot.LoadBalancer.Middleware.LoadBalancingMiddleware.Invoke(HttpContext httpContext) 在 Microsoft.AspNetCore.MiddlewareAnalysis.AnalysisMiddleware.Invoke(HttpContext httpContext) 在 Ocelot.Request.Middleware.DownstreamRequestInitialiserMiddleware.Invoke(HttpContext httpContext) 在 Microsoft.AspNetCore.MiddlewareAnalysis.AnalysisMiddleware .Invoke(HttpContext httpContext) 在 Ocelot.Multiplexer.MultiplexingMiddleware.Invoke(HttpContext httpContext) 在 Microsoft.AspNetCore.MiddlewareAnalysis.AnalysisMiddleware.Invoke(HttpContext httpContext) 在 Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware.Invoke(HttpContext httpContext) 在 Microsoft.AspNetCore Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)在 Microsoft.AspNetCore.MiddlewareAnalysis.AnalysisMiddleware.Invoke(HttpContext httpContext)
以下是我的代码。
Ocelot API 启动文件
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", policy =>
{
policy.SetIsOriginAllowed(x => true).AllowAnyMethod().AllowAnyHeader();
//policy.SetIsOriginAllowed(x => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();
});
});
services.AddSignalR();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseCors("CorsPolicy");
app.UseWebSockets();
app.UseOcelot().Wait();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}
Run Code Online (Sandbox Code Playgroud)
ocelot.json 配置
{
"Routes": [
{
"DownstreamPathTemplate": "/api/currency/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7004
}
],
"UpstreamPathTemplate": "/api-currency/{everything}",
"UpstreamHttpMethod": [ "Get" ]
},
{
"DownstreamPathTemplate": "/api/currency/{everything}",
"ReRouteIsCaseSensitive": false,
"DownstreamScheme": "wss",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7004
}
],
"UpstreamPathTemplate": "/api-currencyhub/{everything}",
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE", "OPTIONS" ]
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:7000",
"RequestIdKey": "OcRequestId"
}
}
Run Code Online (Sandbox Code Playgroud)
微服务API启动文件
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", policy =>
{
policy.SetIsOriginAllowed(x => true).AllowAnyMethod().AllowAnyHeader();
//policy.SetIsOriginAllowed(x => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();
//policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials();
});
});
services.AddSignalR();
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseCors("CorsPolicy");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<CurrencyHub>("/api/currency/maincurrencyhub");
endpoints.MapControllers();
});
}
}
Run Code Online (Sandbox Code Playgroud)
Blazor 客户端 Razor 页面
@page "/"
@using Microsoft.AspNetCore.SignalR.Client
<h1>Hello, world!</h1>
<h1>Welcome to SignalR with Blazor</h1>
<button class="btn btn-success" @onclick="async () => await ConnectToServer()" disabled="@isConnected">Connect</button>
<button class="btn btn-success" @onclick="async () => await OnGateway()">Gateway</button>
<h3>Connection Status: @connectionStatus</h3>
<div class="row">
<div class="col-4">
@foreach (var item in notifications)
{
<div class="row">
<h4>@item</h4>
</div>
}
</div>
</div>
@code {
//string gatewayUrl = "wss://localhost:7000/api-currency/maincurrencyhub";
string gatewayUrl = "https://localhost:7000/api-currency/maincurrencyhub";
HubConnection gatewayConnection = null;
bool isConnected = false;
string connectionStatus = "Closed";
List<string> notifications = new List<string>();
private async Task ConnectToServer()
{
gatewayConnection = new HubConnectionBuilder()
//.WithUrl(gatewayUrl)
.WithUrl(gatewayUrl, opt => { opt.SkipNegotiation = true; opt.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets; })
.Build();
try
{
await gatewayConnection.StartAsync();
connectionStatus = "Connected :-)";
gatewayConnection.Closed += async (s) =>
{
isConnected = false;
connectionStatus = "Disconnected";
await gatewayConnection.StartAsync();
isConnected = true;
};
gatewayConnection.On<string>("ReceiveMessage", m =>
{
notifications.Add(m);
StateHasChanged();
});
}
catch (Exception ex)
{
}
}
async Task OnGateway()
{
await gatewayConnection.InvokeAsync("Send", "Na Gode");
}
}
Run Code Online (Sandbox Code Playgroud)
我试图遵循Ocelot 不将 websocket 传递给微服务的做法,但没有成功。有人可以引导我走向正确的方向吗?
小智 5
这是 Ocelot 配置,最终允许我设置客户端 => Ocelot => signalR 服务器通信。
{
"DownstreamPathTemplate": "/hub/",
"DownstreamScheme": "ws",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 80
}
],
"UpstreamPathTemplate": "/hub/",
"QoSOptions": {
"TimeoutValue": 320000
},
"Priority": 50
},
{
"DownstreamPathTemplate": "/hub/{path}",
"DownstreamScheme": "ws",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 80
}
],
"UpstreamPathTemplate": "/hub/{path}",
"QoSOptions": {
"TimeoutValue": 320000
},
"Priority": 50
},Run Code Online (Sandbox Code Playgroud)
signalR 服务器配置为监听 /hub。
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<MyHub>("hub");
});
Run Code Online (Sandbox Code Playgroud)
我希望它能帮助某人。
| 归档时间: |
|
| 查看次数: |
7474 次 |
| 最近记录: |