.NET 6 Preview 3 中 ASP.NET Core 的更新和改进
原文:bit.ly/2Qb56NP
作者:Daniel Roth
譯者:精致碼農(nóng)-王亮
.NET 6 預(yù)覽版 3 現(xiàn)已推出,其中包括許多對新的 ASP.NET Core 改進(jìn)。以下是本次預(yù)覽版的新內(nèi)容:
更小的 SignalR、Blazor Server、MessagePack 腳本文件
啟用 Redis 分析會(huì)話
HTTP/3 端點(diǎn) TLS 配置
初步 .NET 熱重載支持
Razor 編譯器不再生成單獨(dú)的視圖 Assembly
IIS 中的淺拷貝支持
適用于 SignalR C++ 客戶端的 Vcpkg 端口
減少閑置 TLS 連接的內(nèi)存占用量
從 SlabMemoryPool 中移除板塊
用于 WPF 和 Windows 窗體的 BlazorWebView 控件
1開始
要在.NET 6 Preview 3 中開始使用 ASP.NET Core,請安裝 .NET 6 SDK[1]。
如果你在 Windows 上使用 Visual Studio,我們建議安裝 Visual Studio 2019 16.10 的最新預(yù)覽版。如果你在 macOS 上,我們建議安裝 Visual Studio 2019 for Mac 8.10 的最新預(yù)覽版。
2升級現(xiàn)有項(xiàng)目
要將現(xiàn)有的 ASP.NET Core 應(yīng)用程序從 .NET 6 Preview 2 升級到 .NET 6 Preview 3:
更新所有Microsoft.AspNetCore.*包引用至6.0.0-preview.3.*。
更新所有Microsoft.Extensions.*包引用至6.0.0-preview.3.*。
查看 ASP.NET Core for .NET 6 中的完整中斷性更改列表[2]。
3更小的腳本文件
得益于 Ben Adams 的社區(qū)貢獻(xiàn),SignalR、MessagePack 和 Blazor Server 腳本現(xiàn)在明顯變小了,下載體積減少,瀏覽器解析和編譯 JavaScript 的次數(shù)減少,啟動(dòng)速度加快。
這項(xiàng)工作帶來的下載體積減少是非常驚人的:
| signalr.min.js | 130 KB | 39 KB | 70% | 10 KB |
| blazor.server.js | 212 KB | 116 KB | 45% | 28 KB |
現(xiàn)在你也只需要為 MessagePack 提供@microsoft/signalr-protocol-msgpack包,而不需要包含 msgpack5。這意味著你只需要額外的 29 KB 而不是之前的 140 KB 來使用 MessagePack 而不是 JSON。
下面說下我們是如何減少體積的:
更新 TypeScript 和依賴關(guān)系到最新版本.
將 uglify-js 換成了 terser,這是 webpack 的默認(rèn)版本,支持新的 JavaScript 語言特性(比如class)。
將 SignalR 模塊標(biāo)記為"sideEffects":false,這樣 tree-shaking 就更有效了。
丟棄了 "es6-promise/dist/es6-promise.auto.js"的多邊填充。
更改 TypeScript 為輸出es2019而不是es5,并放棄了es2015.promise和es2015.iterable的 polyfill。
從@msgpack/msgpack移到msgpack5,因?yàn)樗枰俚?polyfills,并且是 TypeScript 和模塊感知的。
你可以在 GitHub 上 Ben 的 PR[3] 中找到更多關(guān)于這些變化的細(xì)節(jié)。
4啟用 Redis 分析會(huì)話
我們接受了 Gabriel Lucaci 的社區(qū)貢獻(xiàn),在此預(yù)覽版中使用Microsoft.Extensions.Caching.StackExchangeRedis啟用 Redis 分析會(huì)話。關(guān)于 Redis 分析的更多細(xì)節(jié),請參見官方文檔[4]。該 API 的使用方法如下:
services.AddStackExchangeRedisCache(options => {options.ProfilingSession = () => new ProfilingSession(); })5HTTP/3 端點(diǎn) TLS 配置
HTTP/3 與現(xiàn)有的 HTTP 協(xié)議相比具有許多優(yōu)勢,包括更快的連接設(shè)置,以及在低質(zhì)量網(wǎng)絡(luò)上的性能改進(jìn)。
在此預(yù)覽版中,新增了使用UseHttps在單個(gè) HTTP/3 端口上配置 TLS 證書的功能。這使得 Kestrel 的 HTTP/3 端點(diǎn)配置與 HTTP/1.1 和 HTTP/2 一致。
.ConfigureKestrel((context, options) => {options.EnableAltSvc = true;options.Listen(IPAddress.Any, 5001, listenOptions =>{listenOptions.Protocols = HttpProtocols.Http3;listenOptions.UseHttps(httpsOptions =>{httpsOptions.ServerCertificate = LoadCertificate();});}); })6初步 .NET 熱重載支持
現(xiàn)在,使用dotnet watch的 ASP.NET Core 和 Blazor 項(xiàng)目可以獲得對 .NET 熱重載的早期支持。.NET 熱重載可以在不重新啟動(dòng)應(yīng)用程序和不丟失應(yīng)用程序狀態(tài)的情況下將代碼更改應(yīng)用到你正在運(yùn)行的應(yīng)用程序中。
要在現(xiàn)有的基于 .NET 6 的 ASP.NET Core 項(xiàng)目中試用熱重載,請將"hotReloadProfile": "aspnetcore"屬性添加到你的launchSettings.json文件中。對于 Blazor WebAssembly 項(xiàng)目,使用"blazorwasm"熱重載配置文件。
使用dotnet watch運(yùn)行項(xiàng)目。下面的輸出表明熱重載已經(jīng)啟用:
watch : Hot reload enabled. For a list of supported edits, see https://aka.ms/dotnet/hot-reload. Press "Ctrl + R" to restart.在任何時(shí)候你想強(qiáng)制應(yīng)用程序重新構(gòu)建和重啟,你可以在控制臺輸入Ctrl+R來實(shí)現(xiàn)。
現(xiàn)在你可以開始對你的代碼進(jìn)行編輯了。當(dāng)你保存代碼更改時(shí),相應(yīng)的更改幾乎會(huì)在瞬間自動(dòng)熱重載到運(yùn)行中的應(yīng)用程序中。運(yùn)行中的應(yīng)用程序中的任何狀態(tài)都會(huì)被保留。
你也可以對你的 CSS 文件進(jìn)行熱重載更改,而不需要刷新瀏覽器:
有一些代碼更改不支持 .NET 執(zhí)重載。你可以在文檔[5]中找到支持的代碼編輯列表。在 Blazor WebAssembly 中,目前只支持方法體替換。我們正在努力擴(kuò)展 .NET 6 中支持的編輯集。當(dāng)dotnet watch檢測到無法使用熱重載應(yīng)用的更改時(shí),它就會(huì)退回重新構(gòu)建和重新啟動(dòng)應(yīng)用程序。
這只是 .NET 6 中熱重載支持的開始。桌面和移動(dòng)應(yīng)用程序的熱重載支持將很快在即將到來的預(yù)覽版中提供,以及在 Visual Studio 中集成熱重載。
7IIS 中的淺拷貝支持
我們在 IIS 的 ASP.NET Core 模塊中添加了一個(gè)新功能,以增加對淺拷貝應(yīng)用程序程序集的支持。目前,.NET 在 Windows 上運(yùn)行時(shí)鎖定了應(yīng)用程序的二進(jìn)制文件,使得在應(yīng)用程序仍在運(yùn)行時(shí)無法替換二進(jìn)制文件。雖然我們的建議仍然是使用應(yīng)用程序脫機(jī)文件,但我們認(rèn)識到在某些情況下(例如 FTP 部署)不可能這樣做。
在這種情況下,你可以通過自定義 ASP.NET Core 模塊處理程序設(shè)置來啟用淺拷貝。在大多數(shù)情況下,ASP.NET Core 應(yīng)用程序的web.config不在源代碼版本控制中,你可以修改它(它們通常是由 SDK 生成的)。你可以添加這個(gè)web.config示例來開始。
<?xml version="1.0" encoding="utf-8"?> <configuration><!-- To customize the asp.net core module uncomment and edit the following p.For more info see https://go.microsoft.com/fwlink/?linkid=838655 --><system.webServer><handlers><remove?name="aspNetCore"/><add?name="aspNetCore"?path="*"?verb="*"?modules="AspNetCoreModulev2"?resourceType="Unspecified"/></handlers><aspNetCore?processPath="%LAUNCHER_PATH%"?arguments="%LAUNCHER_ARGS%"?stdoutLogEnabled="false"?stdoutLogFile=".\logs\stdout"><handlerSettings><handlerSetting?name="experimentalEnableShadowCopy"?value="true" /><handlerSetting?name="shadowCopyDirectory"?value="../ShadowCopyDirectory/" /><!-- Only enable handler logging if you encounter issues--><!--<handlerSetting name="debugFile" value=".\logs\aspnetcore-debug.log" />--><!--<handlerSetting name="debugLevel" value="FILE,TRACE" />--></handlerSettings></aspNetCore></system.webServer> </configuration>你需要一個(gè)新版本的 ASP.NET Core 模塊來嘗試這個(gè)功能。在自托管的 IIS 服務(wù)器上,這需要新版本的托管捆綁包。在 Azure App Services 上,你需要安裝新的 ASP.NET Core 站點(diǎn)運(yùn)行時(shí)擴(kuò)展。
8適用于 SignalR C++ 客戶端的 Vcpkg 端口
Vcpkg 是一個(gè)跨平臺的 C 和 C++庫的命令行包管理器。最近,我們?yōu)?vcpkg 添加了一個(gè)移植版本,為 SignalR C++ 客戶端添加了 CMake 本地支持(也適用于 MSBuild 項(xiàng)目)。
你可以用下面的代碼來添加 SignalR 客戶端到你的 CMake 項(xiàng)目中(假設(shè)你已經(jīng)包含了 vcpkg 工具鏈文件)。
find_package(microsoft-signalr CONFIG REQUIRED) link_libraries(microsoft-signalr::microsoft-signalr)在這之后,SignalR C++ 客戶端就可以被#include并用于你的項(xiàng)目中,而不需要任何額外的配置。這個(gè)倉庫[6]是一個(gè)完整的使用 SignalR C++ 客戶端的 C++ 應(yīng)用程序的例子。
9減少閑置 TLS 連接的內(nèi)存占用量
對于只偶爾來回發(fā)送數(shù)據(jù)的 TLS 長連接,我們已經(jīng)大大減少了 .NET 6 中 ASP.NET Core 應(yīng)用程序的內(nèi)存占用。這應(yīng)該有助于提高 WebSocket 服務(wù)器等場景的可擴(kuò)展性。這得益于System.IO.Pipelines、SslStream和Kestrel的眾多改進(jìn)。讓我們來看看促成這一方案的一些改進(jìn)。
縮減 System.IO.Pipelines.Pipe 大小
對于我們建立的每一個(gè)連接,我們都會(huì)在 Kestrel 中分配兩個(gè)管道:一個(gè)是從傳輸層到應(yīng)用的請求,另一個(gè)是從應(yīng)用層到傳輸?shù)捻憫?yīng)。通過將System.IO.Pipelines.Pipe的大小從 368 字節(jié)縮減到 264 字節(jié)(約 28.2%),我們?yōu)槊總€(gè)連接節(jié)省了 208 字節(jié)(每個(gè) Pipe 節(jié)省 104 字節(jié))。
SocketSender 池
SocketSender 對象在運(yùn)行時(shí)約為 350 字節(jié)。與其為每個(gè)連接分配一個(gè)新的 SocketSender 對象,我們可以將它們集中起來,因?yàn)榘l(fā)送通常非常快,我們可以減少每個(gè)連接的開銷。現(xiàn)在,我們不再為每個(gè)連接分配 350 字節(jié),而是只為每個(gè) IOQueue 分配 350 字節(jié)(每個(gè)隊(duì)列一個(gè),以避免爭用)。在擁有 5000 個(gè)空閑連接的 WebSocket 服務(wù)器中,我們從分配約 1.75 MB(350 字節(jié)*5000)到現(xiàn)在只分配約 2.8kb(350 字節(jié)*8)給 SocketSender 對象。
SslStream 零字節(jié)讀取
無緩沖讀取是我們已經(jīng)在 ASP.NET Core 中采用的一種技術(shù),以避免在套接字上沒有可用數(shù)據(jù)時(shí)從內(nèi)存池中租用內(nèi)存。在這一變化之前,我們的 WebSocket 服務(wù)器有 5000 個(gè)空閑連接,在沒有 TLS 的情況下需要約 200 MB,而在有 TLS 的情況下需要約 800 MB。其中一些分配(每個(gè)連接 4k)是由于 Kestrel 在等待SslStream上的讀取完成時(shí)必須保持ArrayPool緩沖區(qū)。鑒于這些連接是空閑的,沒有一個(gè)讀取完成并將其緩沖區(qū)返回給ArrayPool,迫使ArrayPool分配更多的內(nèi)存。剩余的分配都在SslStream本身。4k 緩沖區(qū)用于 TLS 握手,32k 緩沖區(qū)用于正常讀取。在預(yù)覽版 3 中,當(dāng)用戶在SslStream上執(zhí)行零字節(jié)讀取,而它又沒有可用的數(shù)據(jù)時(shí),SslStream會(huì)在內(nèi)部對底層的封裝流執(zhí)行零字節(jié)讀取。在最好的情況下(空閑連接),這些變化導(dǎo)致每個(gè)連接節(jié)省了 40 Kb,同時(shí)仍然允許消費(fèi)者(Kestrel)在數(shù)據(jù)可用時(shí)得到通知,而無需保留任何未使用的緩沖區(qū)。
PipeReader 零字節(jié)讀取
一旦SslStream支持無緩沖區(qū)讀取,我們就向StreamPipeReader(將Stream適配成PipeReader的內(nèi)部類型)添加了執(zhí)行零字節(jié)讀取的選項(xiàng)。在 Kestrel 中,我們使用StreamPipeReader將底層的SslStream適配成PipeReader,有必要在PipeReader上暴露這些零字節(jié)讀取語義。
現(xiàn)在,你可以使用以下 API 創(chuàng)建一個(gè)PipeReader,支持在任何支持零字節(jié)讀取語義的Stream上進(jìn)行零字節(jié)讀取(例如SslStream、NetworkStream等)。
var reader = PipeReader.Create(stream, new StreamPipeReaderOptions(useZeroByteReads: true));10從 SlabMemoryPool 中移除板塊
為了減少堆的碎片,Kestrel 采用了一種技術(shù),它分配了 128 KB 的內(nèi)存板塊作為其內(nèi)存池的一部分。然后,這些板塊被進(jìn)一步劃分為 4 KB 的塊,供 Kestrel 內(nèi)部使用。板塊必須大于 85 KB,以便在大對象堆上強(qiáng)制分配,以盡量防止 GC 重新定位這個(gè)陣列。然而,隨著新一代 GC 的引入,Pinned Object Heap(POH),在板塊上分配塊已經(jīng)沒有意義了。在預(yù)覽版 3 中,我們現(xiàn)在直接在 POH 上分配塊[7],降低了管理自己的內(nèi)存池所涉及的復(fù)雜性。這個(gè)變化應(yīng)該可以更容易地執(zhí)行未來的改進(jìn),比如讓 Kestrel 使用的內(nèi)存池更容易收減。
11用于 WPF 和 Windows 窗體的 BlazorWebView 控件
對于 .NET 6,我們增加了對使用 .NET MAUI 和 Blazor 構(gòu)建跨平臺混合桌面應(yīng)用程序的支持。混合應(yīng)用程序是利用 Web 技術(shù)實(shí)現(xiàn)其功能的本地應(yīng)用程序。例如,一個(gè)混合應(yīng)用程序可能會(huì)使用一個(gè)嵌入式的 Web 視圖控件來渲染 Web UI。這意味著你可以使用 HTML 和 CSS 等 Web 技術(shù)編寫應(yīng)用程序 UI,同時(shí)還可以使用本地設(shè)備的功能。我們將在即將發(fā)布的 .NET 6 預(yù)覽版中引入對使用 .NET MAUI 和 Blazor 構(gòu)建混合應(yīng)用程序的支持。
在這個(gè)版本中,我們?yōu)?WPF 和 Windows Forms 應(yīng)用程序引入了BlazorWebView控件,該控件可將 Blazor 功能嵌入到基于 .NET 6 的現(xiàn)有 Windows 桌面應(yīng)用程序中。使用 Blazor 和混合方式,你可以將你的 UI 與 WPF 和 Windows Forms 解耦。這是一種對現(xiàn)有桌面應(yīng)用程序進(jìn)行現(xiàn)代化改造的好方法,可以將其帶到 .NET MAUI 上或在 Web 上使用。你可以使用 Blazor 對現(xiàn)有的 Windows Forms 和 WPF 應(yīng)用程序進(jìn)行現(xiàn)代化改造。
要使用新的BlazorWebView控件,你首先需要確保你已經(jīng)安裝了 WebView2[8]。
要將 Blazor 功能添加到現(xiàn)有的 Windows Forms 應(yīng)用程序中,需要:
更新 Windows Forms 應(yīng)用程序,使其 Target 為 .NET 6。
把應(yīng)用程序項(xiàng)目文件中的 SDK 更新為 Microsoft.NET.Sdk.Razor。
添加Microsoft.AspNetCore.Components.WebView.WindowsForms包引用。
在項(xiàng)目中添加以下wwwroot/index.html文件,用實(shí)際的項(xiàng)目名稱替換{PROJECT NAME}:
<!DOCTYPE html> <html><head><meta?charset="utf-8" /><metaname="viewport"content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/><title>Blazor app</title><base?href="/" /><link?href="{PROJECT NAME}.styles.css"?rel="stylesheet" /><link?href="app.css"?rel="stylesheet" /></head><body><div?id="app"></div><div?id="blazor-error-ui">An unhandled error has occurred.<a?href=""?class="reload">Reload</a><a?class="dismiss">????</a></div><script?src="_framework/blazor.webview.js"></script></body> </html>在 wwwroot 文件夾中添加以下app.css文件,包含一些基本樣式:
html, body {font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; }.valid.modified:not([type='checkbox']) {outline: 1px solid #26b050; }.invalid {outline: 1px solid red; }.validation-message {color: red; }#blazor-error-ui {background: lightyellow;bottom: 0;box-shadow: 0 -1px?2px?rgba(0, 0, 0, 0.2);display: none;left: 0;padding: 0.6rem?1.25rem?0.7rem?1.25rem;position: fixed;width: 100%;z-index: 1000; }#blazor-error-ui?.dismiss {cursor: pointer;position: absolute;right: 0.75rem;top: 0.5rem; }對于 wwwroot 文件夾中的所有文件,將Copy to Output Directory屬性設(shè)置為Copy if newer。
在項(xiàng)目中添加一個(gè) Blazor 根組件Counter.razor:
@using Microsoft.AspNetCore.Components.Web<h1>Counter</h1><p>The current count is: @currentCount</p> <button @onclick="IncrementCount">Count</button>@code {int currentCount = 0;void?IncrementCount(){currentCount++;} }將BlazorWebView控件添加到所需的表單中,以渲染 Blazor 根組件:
var serviceCollection = new ServiceCollection(); serviceCollection.AddBlazorWebView(); var blazor = new BlazorWebView() {Dock = DockStyle.Fill,HostPage = "wwwroot/index.html",Services = serviceCollection.BuildServiceProvider(), }; blazor.RootComponents.Add<Counter>("#app"); Controls.Add(blazor);運(yùn)行該應(yīng)用程序,查看BlazorWebView的運(yùn)行情況。
要將 Blazor 功能添加到現(xiàn)有的 WPF 應(yīng)用程序中,請按照上面列出的 Windows 窗體應(yīng)用程序的相同步驟進(jìn)行操作。另外:
為Microsoft.AspNetCore.Components.WebView.Wpf替換包引用。
在 XAML 中添加BlazorWebView控件:
<Window?x:Class="WpfApp1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApp1"xmlns:blazor="clr-namespace:Microsoft.AspNetCore.Components.WebView.Wpf;assembly=Microsoft.AspNetCore.Components.WebView.Wpf"mc:Ignorable="d"Title="MainWindow"?Height="450"?Width="800"><Grid><blazor:BlazorWebView?HostPage="wwwroot/index.html"?Services="{StaticResource services}"><blazor:BlazorWebView.RootComponents><blazor:RootComponent?Selector="#app"?ComponentType="{x:Type local:Counter}" /></blazor:BlazorWebView.RootComponents></blazor:BlazorWebView></Grid> </Window>將服務(wù)提供者設(shè)置為靜態(tài)資源:
var serviceCollection = new ServiceCollection(); serviceCollection.AddBlazorWebView(); Resources.Add("services", serviceCollection.BuildServiceProvider());為了解決 WPF 運(yùn)行時(shí)構(gòu)建時(shí)找不到 Razor 組件類型的問題,在Counter.razor.cs中為組件添加一個(gè)空的局部類:
public?partial?class?Counter { }構(gòu)建并運(yùn)行基于 Blazor 的 WPF 應(yīng)用:
12提供反饋
我們希望你喜歡這個(gè) .NET 6 預(yù)覽版中的 ASP.NET Core 部分。我們渴望聽到你對這個(gè)版本的體驗(yàn)。請?jiān)?GitHub 上提交 Issue,讓我們知道你的想法。
謝謝你試用 ASP.NET Core!
文中鏈接:
https://dotnet.microsoft.com/download/dotnet/6.0 https://docs.microsoft.com/zh-cn/dotnet/core/compatibility/6.0#aspnet-core https://github.com/dotnet/aspnetcore/pull/30320 https://stackexchange.github.io/StackExchange.Redis/Profiling_v2.html https://docs.microsoft.com/visualstudio/debugger/supported-code-changes-csharp https://github.com/halter73/SignalR-Client-Cpp-Sample https://github.com/dotnet/aspnetcore/pull/30732 https://developer.microsoft.com/microsoft-edge/webview2/#download-p 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的.NET 6 Preview 3 中 ASP.NET Core 的更新和改进的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .Net5 WPF快速入门系列教程
- 下一篇: 以IP段作为监听地址