[[415137]]
本文转载自微信公众号「缜密码农」,作家liamwang。转载本文请经营缜密码农公众号。
针孔摄像头酒店偷拍早在 2019 年,我写过《用 Mapbox 绘图位置数据》一文,宝贵先容了我若何通过通俗的文献上传,用 Mapbox 绘图约 230 万个位置点。本文先容我是若何通过使用 gRPC 和 .NET Core 的就业器流来快速获取所有位置历史数据的。
针孔摄像头酒店偷拍IDhttps://chandankkrr.medium.com/mapping-location-data-with-mapbox-9b256f64d569什么是 gRPC
gRPC 是一个当代开源的高性能 RPC 框架,不错在职何环境下运转。它不错灵验地鸠合数据中心内和跨数据中心的就业,并对负载均衡、追踪、健康检查和认证提供可插拔的支柱。gRPC 率先是由谷歌创建的,该公司使用一个名为 Stubby 的单一通用 RPC 基础法子来鸠合其数据中心内和跨数据中心运转的大量微就业,使用依然跳动十年。2015 年 3 月,谷歌决定建造 Stubby 的下一个版块,并将其开源,恶果等于咫尺的 gRPC,被好多企业或组织使用。
针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍IDhttps://grpc.io/gRPC 就业器流
就业器流式(Server Streaming)RPC,客户端向就业器发送央求,并获取一个流来读取一连串的讯息。客户端从复返的流中读取信息,直到莫得讯息适度。gRPC 保证在单个 RPC 调用中的信息是有序的。
针孔摄像头酒店偷拍IDrpc GetLocationData (GetLocationRequest) returns (stream GetLocationResponse);
针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID 公约缓冲区(Protobuf)gRPC 使用公约缓冲区(protocol buffers)当作接口界说话语(IDL)来界说客户端和就业器之间的契约。不才面的 proto 文献中,界说了一个 RPC 秩序 GetLocations,它给与 GetLocationsRequest 讯息类型并复返 GetLocationsResponse 讯息类型。反应讯息类型前边的 stream 关键字暗示反应是流类型,而不是单个反应。
针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍IDsyntax = "proto3"; option csharp_namespace = "GPRCStreaming"; package location_data; service LocationData { rpc GetLocations (GetLocationsRequest) returns (stream GetLocationsResponse); } message GetLocationsRequest { int32 dataLimit = 1; } message GetLocationsResponse { int32 latitudeE7 = 1; int32 longitudeE7 = 2; }
创建 gRPC 就业
咱们不错使用 dotnet new grpc -n threemillion 号令松驰创建一个 .NET gRPC 就业。更多对于在 ASP.NET Core 中创建 gRPC 就业器和客户端的信息可在微软文档中找到。
针孔摄像头酒店偷拍ID365建站春药首选网店可货到付款针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID
Create a gRPC client and server in ASP.NET Core https://docs.microsoft.com/en-us/aspnet/core/tutorials/grpc/grpc-start?view=aspnetcore-5.0&tabs=visual-studio-code
在添加了 proto 文献并生成了 gRPC 就业资源文献后,接下来我添加了 LocationService 类。不才面的代码片断中,我有一个 LocationService 类,它承袭了从 Location.proto 文献中生成的 LocationDataBase 类型。客户端不错通过 Startup.cs 文献中 Configure 秩序中的 endpoints.MapGrpcService() 来探望 LocationService。当就业器收到 GetLocations 央求时,它最先通过 GetLocationData 秩序调用读取 Data 文献夹中 LocationHistory.json 文献中的所罕有据(未包含在源代码库)。该秩序复返 RootLocation 类型,其中包含 List 类型的 Location 属性。Location 类由两个里面属性 Longitude 和 Latitude 构成。接下来,我轮回浏览每个位置,然后将它们写入 responseStream 中,复返给客户端。就业器将讯息写入流中,直到客户在 GetLocationRequest 对象中指定的 dataLimit。
针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID
using System.Threading.Tasks; using Grpc.Core; using Microsoft.Extensions.Logging; using System.IO; using System; using System.Linq; namespace GPRCStreaming { public class LocationService : LocationData.LocationDataBase { private readonly FileReader _fileReader; private readonly ILogger<LocationService> _logger; public LocationService(FileReader fileReader, ILogger<LocationService> logger) { _fileReader = fileReader; _logger = logger; } public override async Task GetLocations( GetLocationsRequest request, IServerStreamWriter<GetLocationsResponse> responseStream, ServerCallContext context) { try { _logger.LogInformation("Incoming request for GetLocationData"); var locationData = await GetLocationData(); var locationDataCount = locationData.Locations.Count; var dataLimit = request.DataLimit > locationDataCount ? locationDataCount : request.DataLimit; for (var i = 0; i <= dataLimit - 1; i++) { var item = locationData.Locations[i]; await responseStream.WriteAsync(new GetLocationsResponse { LatitudeE7 = item.LatitudeE7, LongitudeE7 = item.LongitudeE7 }); } } catch (Exception exception) { _logger.LogError(exception, "Error occurred"); throw; } } private async Task<RootLocation> GetLocationData() { var currentDirectory = Directory.GetCurrentDirectory(); var filePath = $"{currentDirectory}/Data/Location_History.json"; var locationData = await _fileReader.ReadAllLinesAsync(filePath); return locationData; } } }
迷水商城针孔摄像头酒店偷拍ID
咫尺,让咱们运转该就业并发送一个央求。我将使用一个叫 grpcurl 的号令行器具,它不错让你与 gRPC 就业器交互。它基本上是针对 gRPC 就业器的 curl。
针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID
https://github.com/fullstorydev/grpcurl
通过 grpcurl 与 gRPC 端点(endpoint)交互只好在 gRPC 反射就业被启用时才可用。这允许就业不错被查询,以发现就业器上的 gRPC 就业。延长秩序 MapGrpcReflectionService 需要引入 Microsoft.AspNetCore.Builder 的定名空间:
针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseEndpoints(endpoints => { endpoints.MapGrpcService<LocationService>(); if (env.IsDevelopment()) { endpoints.MapGrpcReflectionService(); } endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909"); }); }); }
针孔摄像头酒店偷拍ID
grpcurl -plaintext -d '{"dataLimit": "100000"}' localhost:80 location_data.LocationData/GetLocations
一朝就业器收到央求,它就会读取文献,然后在位置列表中轮回,直到达到 dataLimit 计数,并将位置数据复返给客户端。
针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID
接下来,让咱们创建一个 Blazor 客户端来调用 gRPC 就业。咱们不错使用 IServiceCollection 接口上的 AddGrpcClient 延长秩序建立一个 gRPC 客户端:
针孔摄像头酒店偷拍ID
public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddServerSideBlazor(); services.AddSingleton<WeatherForecastService>(); services.AddGrpcClient<LocationData.LocationDataClient>(client => { client.Address = new Uri("http://localhost:80"); }); }
针孔摄像头酒店偷拍ID
我使用 Virtualize Blazor 组件来渲染这些位置。Virtualize 组件不是一次性渲染列表中的每个时势,只好面前可见的时势才会被渲染。
针孔摄像头酒店偷拍ID针孔摄像头酒店偷拍ID
ASP.NET Core Blazor component virtualization https://docs.microsoft.com/en-us/aspnet/core/blazor/components/virtualization?view=aspnetcore-5.0
针孔摄像头酒店偷拍ID迷水商城
联系代码:
针孔摄像头酒店偷拍ID
@page "/locationdata" @using Grpc.Core @using GPRCStreaming @using threemillion.Data @using System.Diagnostics @using Microsoft.AspNetCore.Components.Web.Virtualization @inject IJSRuntime JSRuntime; @inject System.Net.Http.IHttpClientFactory _clientFactory @inject GPRCStreaming.LocationData.LocationDataClient _locationDataClient <table class="tableAction"> <tbody> <tr> <td> <div class="data-input"> <label for="dataLimit">No of records to fetch</label> <input id="dataLimit" type="number" @bind="_dataLimit" /> <button @onclick="FetchData" class="btn-submit">Call gRPC</button> </div> </td> <td> <p class="info"> Total records: <span class="count">@_locations.Count</span> </p> <p class="info"> Time taken: <span class="time">@_stopWatch.ElapsedMilliseconds</span> milliseconds </p> </td> </tr> </tbody> </table> <div class="tableFixHead"> <table class="table"> <thead> <tr> <th>Longitude</th> <th>Latitude</th> </tr> </thead> <tbody> <Virtualize Items="@_locations" Context="locations"> <tr> <td>@locations.LongitudeE7</td> <td>@locations.LatitudeE7</td> </tr> </Virtualize> </tbody> </table> </div> @code { private int _dataLimit = 1000; private List<Location> _locations = new List<Location>(); private Stopwatch _stopWatch = new Stopwatch(); protected override async Task OnInitializedAsync() { await FetchData(); } private async Task FetchData() { ResetState(); _stopWatch.Start(); using (var call = _locationDataClient.GetLocations(new GetLocationsRequest { DataLimit = _dataLimit })) { await foreach (var response in call.ResponseStream.ReadAllAsync()) { _locations.Add(new Location { LongitudeE7 = response.LongitudeE7, LatitudeE7 = response.LatitudeE7 }); StateHasChanged(); } } _stopWatch.Stop(); } private void ResetState() { _locations.Clear(); _stopWatch.Reset(); StateHasChanged(); } }
针孔摄像头酒店偷拍ID

通过在腹地运转的流调用,从 gRPC 就业器给与 2,876,679 个单独的反应苟简需要 8 秒钟。让咱们也在 Mapbox 中加载数据:
@page "/mapbox" @using Grpc.Core @using GPRCStreaming @using System.Diagnostics @inject IJSRuntime JSRuntime; @inject System.Net.Http.IHttpClientFactory _clientFactory @inject GPRCStreaming.LocationData.LocationDataClient LocationDataClient <table class="tableAction"> <tbody> <tr> <td> <div class="data-input"> <label for="dataLimit">No of records to fetch</label> <input id="dataLimit" type="number" @bind="_dataLimit" /> <button @onclick="LoadMap" class="btn-submit">Load data</button> </div> </td> <td> <p class="info"> Total records: <span class="count">@_locations.Count</span> </p> <p class="info"> Time taken: <span class="time">@_stopWatch.ElapsedMilliseconds</span> milliseconds </p> </td> </tr> </tbody> </table> <div id='map' style="width: 100%; height: 90vh;"></div> @code { private int _dataLimit = 100; private List<object> _locations = new List<object>(); private Stopwatch _stopWatch = new Stopwatch(); protected override async Task OnAfterRenderAsync(bool firstRender) { if (!firstRender) { return; } await JSRuntime.InvokeVoidAsync("mapBoxFunctions.initMapBox"); } private async Task LoadMap() { ResetState(); _stopWatch.Start(); using (var call = LocationDataClient.GetLocations(new GetLocationsRequest { DataLimit = _dataLimit })) { await foreach (var response in call.ResponseStream.ReadAllAsync()) { var pow = Math.Pow(10, 7); var longitude = response.LongitudeE7 / pow; var latitude = response.LatitudeE7 / pow; _locations.Add(new { type = "Feature", geometry = new { type = "Point", coordinates = new double[] { longitude, latitude } } }); StateHasChanged(); } _stopWatch.Stop(); await JSRuntime.InvokeVoidAsync("mapBoxFunctions.addClusterData", _locations); } } private void ResetState() { JSRuntime.InvokeVoidAsync("mapBoxFunctions.clearClusterData"); _locations.Clear(); _stopWatch.Reset(); StateHasChanged(); } }

源代码在我的 GitHub 上 :
https://github.com/Chandankkrr/threemillion