大家好,我是張飛洪,感謝您的閱讀,我會不定期和你分享學習心得,希望我的文章能成爲你成長路上的墊腳石,讓我們一起精進。
本章是《定製ASP NET 6.0框架系列文章》的第六篇。在本章中,我們將討論如何在ASP NET 6.0中自定義託管宿主。比如,託管選項和不同類型的託管,並瞭解一下IIS上的託管。限於篇幅,本章只是一個拋磚迎玉。
本章涵蓋主題包括:
- 配置WebHostBuilder
- 配置Kestrel
- 配置HTTP.sys
- IIS上的託管
- 在Linux上使用Nginx或Apache
本章涉及的服務端體系結構主題包括:
1 準備
代碼準備
我們先創建一個空運用:
dotnet new web -n ExploreHosting -o ExploreHosting
然後使用VS Code打開該項目:
cd ExploreHosting code .
名詞解釋:
Hosting 有些地方叫宿主,有些地方叫託管,還有的地方叫承載,爲了行文方便,我這裏統一叫託管,我們知道他們是同一個意思就行。
2 配置WebHostBuilder
與上一章一樣,這個小節我們將重點放在Program.cs上。WebHostBuilder是託管的重要類,它是我們配置和創建Web託管的地方。
以下代碼是每個新創建的ASP.NET Core Web項目默認的代碼:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
正如我們前面所瞭解的,默認框架已經幫我們配置了基本的內容,我們可以在在Azure或本地IIS上直接運行。顯然以上的配置是最基礎的,你完全可以覆寫這些默認配置,包括託管的配置。
下面我們一起來看下Kestrel如何配置。
3 配置Kestrel
創建好WebHostBuilder後,我們可以使用各種方法來配置builder。這裏,我們只舉例一種,即使用Startup類。
在第4章:使用Kestrel配置和自定義HTTPS中我提到,Kestrel是託管應用程序的一種選項,它內置於.NET的Web服務器,基於.NET套接字實現。以前,它是在libuv之上構建的,libuv與Node.js使用相同的web服務器。Microsoft刪除了對libuv的依賴,並基於.NET套接字創建了自己的Web服務器Kestrel。
在上一章中,我們使用UseKestrel方法來配置Kestrel選項:
.UseKestrel((host, options) => { // ... })
如上代碼所示,第一個參數是WebHostBuilderContext,用於訪問已配置的主機設置或配置本身。第二個參數是配置Kestrel的對象。
下面的代碼片段顯示的是我們在上一章中所做的託管配置需要監聽的訪問地址:
builder.WebHost.UseKestrel((host, options) => {
var filename = host.Configuration.GetValue("AppSettings:certfilename", "");
var password = host.Configuration.GetValue("AppSettings:certpassword", "");
options.Listen(IPAddress.Loopback, 5000);
options.Listen(IPAddress.Loopback, 5001, listenOptions => {
listenOptions.UseHttps(filename, password);
});
});
注意:在中添加一個using一個System.Net名稱空間。
以上代碼演示的是覆蓋默認配置,您可以在其中傳入URL,例如,使用launchSettings.json文件的applicationUrl屬性或環境變量。
接下來,我們看看如何設置HTTP.sys。
4 配置HTTP.sys
這裏介紹另一個託管選項HTTP.sys,一個不同的Web服務器的實現。它是一個非常成熟的庫,默認嵌入到Windows中,可以用來託管ASP.NET Core應用程序:
.UseHttpSys(options => { // ... })
HTTP.sys不同於Kestrel,它不能在IIS中使用,因爲對於IIS來說,它與ASP.NET Core模塊無法兼容。
使用HTTP.sys而不是Kestrel的主要原因是:Windows身份驗證不能在Kestrel中使用。另外,如果你想將自己的應用暴露到公網當中,當時你又不想使用IIS,也可以使用HTTP.sys。
多年來,IIS一直在HTTP.sys之上運行,這意味着使用UseHttpSys()相當於IIS內部使用相同的Web服務器實現。瞭解有關HTTP.sys的更多信息,可以訪問該地址。
接下來,讓我們看看使用IIS託管。
5 IIS上的託管
ASP.NET Core應用程序不應直接暴露於internet,即使它支持Kestrel或HTTP.sys。最好在兩者之間有一個反向代理,或者至少有一個監視託管過程的服務。對於ASP.NET Core來說,IIS不僅僅是一個反向代理。它還負責託管進程,以防由於錯誤而中斷。如果發生錯誤,IIS將重新啓動進程。Nginx和IIS類似,主要是用在Linux上的反向代理,也負責託管過程。
假設你已經創建了一個新項目(刪除Kestrel相關配置,對IIS不起作用)。
在IIS或Azure上託管ASP.NET Core Web之前,我們需要先編譯併發布應用。
dotnet publish -o ..\published -r win-x64
編譯後生成的文件可以部署在IIS上,另外它還生成了一個web.config,用於配置IIS或Azure的設置。
如果發佈一個自包含的應用程序,它還包含運行時本身,即.NET Core運行時,但是交付時的大小增加了很多。而在IIS上只需創建一個新網站並將其映射到發佈輸出的文件夾即可。如果你需要考慮更改安全相關內容,或者帶一些數據庫連接等等,它會變得更加複雜,這不是一篇文章能搞定的。
6 在Linux上使用Nginx或Apache
在Linux上的發佈ASP.NET Core應用和IIS上非常相似,因爲沒有了IIS這個反向代理,所以我們需要爲反向代理做準備額外的步驟。一般我們會選擇一個網絡服務器,如Nginx或Apache作爲反向代理,將流量轉發給Kestrel和ASP.NET Core應用程序。
首先,我們需要應用接受兩個特定的轉發頭,打開Startup.cs並在UseAuthentication中間件之前的Configure方法中添加以下行:
app.UseForwardedHeaders(new ForwardedHeadersOptions {
ForwardedHeaders = ForwardedHeaders.XForwardedFor|ForwardedHeaders.XForwardedProto
});
另外,還需要添加來自反向代理的傳入流量信任,爲此需要向ConfigureServices方法添加以下行:
Builder.Services.Configure<ForwardedHeadersOptions>(options => {
options.KnownProxies.Add(IPAddress.Parse("10.0.0.108"));
});
這裏別忘了引入Microsoft.AspNetCore.HttpOverrides
名稱空間。
這裏演示的是添加代理的IP地址,然後我們發佈應用程序:
dotnet publish --configuration Release
將生成的文件複製到名爲/var/www/yourapplication的文件夾中。你可以通過以下命令在Linux上進行快速測試:
dotnet <yourapplication.dll>
這裏的yourapplication.dll是已編譯的應用程序,包括路徑。如果一切正常,我們就能夠在http://localhost:5000/訪問我們的站點。
如果訪問一切正常,應用程序應該作爲服務運行,我們需要在/etc/systemd/system/上創建一個服務文件,可以將文件命名爲kestrel-yourapplication.service,在其中配置以下內容:
[Unit] Description=Example .NET Web API App running on Ubuntu
[Service] WorkingDirectory=/var/www/yourapplication ExecStart=/usr/bin/dotnet/var/www/yourapplication/yourapplication.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10 KillSignal=SIGINT SyslogIdentifier=dotnet-example User=www-data Environment=ASPNETCORE_ENVIRONMENT=Production Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false [Install] WantedBy=multi-user.target
1.確保配置裏的路徑指向編譯生成的文件夾。
2.此文件配置了應用程序應在默認端口上作爲服務運行。
3.監視應用程序並在其崩潰時重新啓動。
4.定義了來自環境變量的配置(請參閱第1章“自定義日誌記錄”,瞭解如何使用環境變量配置應用程序)。
接下來,我們看下如何配置Nginx。
6.1配置Nginx
接下來,我們可以在Nginx上進行配置了:
server {
listen 80;
server_name example.com *.example.com;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
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;
}
}
以上代碼告訴Nginx將端口80
上的調用轉發給example.com
及其子域http://localhost:5000
,這是應用程序的默認地址。
6.2配置Apache
Apache配置看起來非常類似於Nginx方法,幾乎做了相同的事情:
<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto expr=%{REQUEST_SCHEME}
</VirtualHost>
<VirtualHost *:80>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
ServerName www.example.com
ServerAlias *.example.com
ErrorLog ${APACHE_LOG_DIR}yourapplication-error.log
CustomLog ${APACHE_LOG_DIR}yourapplication-access.log
common
</VirtualHost>
以上就是Nginx和Apache的配置內容,更多細節需要你擼起袖子細細體驗了。
回顧
ASP.NET Core和.NET CLI已經包含了在各種平臺上運行的所有工具,並默認進行了設置,以便爲Azure和IIS以及Nginx做好準備。
在.NET 6.0我們用的是WebHostBuilder,它創建了應用程序的託管環境。但是在之前的3.0版本中,我們用的是HostBuilder,它能夠創建完全獨立於任何Web上下文託管環境。
ASP.NET Core 6.0具有在程序後臺運行駐守任務的能力,具體介紹,請期待我們的下一章《使用IHostedService和BackgroundService》。