.NET Core 遷移躺坑記

最近將本身負責的一個核心接口系統從.Net Framework遷移到了.Net Core。html

總體過程,從業務層面說通常般吧(總體還好但仍是搞的業務有感,沒出嚴重故障)可是技術層面上感受其實並無達到要求,不過預期也是應該不會那麼順利,接下來可能還須要幾個小Fix來處理各類奇奇怪怪的問題。git

回顧下遷移時候遇到的若干個坑,但願對後續有此類操做的人全部幫助。github

 

1.NetCore下的路由行爲和Web Api的不一致

咱們回顧下在Web Api裏時候的一個路由定義redis

image

這個配置下可讓shell

Get RootUrl/123Get RootUrl?id=123 同時映射到 GetThirdPartyChannel方法裏。json

可是,假如在不作改動前提下直接將這個Controller定義變爲Core的話,Get RootUrl?id=123 這個路由將沒法正常運做 (而 Get RootUrl/123 則依然能夠正常運行)。api

緣由是在AspNetCore下他發現了[Route(「{Id}」)]就會認爲Id是Path的一部分,而後至關於隱式給id這個參數默認了[FromPath],可是[Route(「」)]這裏並無定義id做爲Path。服務器

會致使一旦調用 Get RootUrl?id=123 的時候,首先路由是能匹配上 [Route(「」)]的,可是參數裏的id恆定是空(即代碼裏獲取到的id字段永遠是null)。異步

 

解決方案有2種

①強制在方法參數的id里加上[FromQuery],可是這個會有個咖喱是Swagger生成的文檔裏會有2個Id字段(Path裏有一個,你強制了Query裏有一個)可是接口能正常工做;socket

②將2個路由拆開來分別對應2個方法。

 

總結:

按照咱們組內規範,定義Url是不能放Path的,這些都是一些早期設計的,沒有遵守規範將其替換完一直遺留着,規範不嚴格,代碼兩行淚。

 

2.NetCore下加載程序集的時候會識別版本號

咱們有使用到部分的類庫會依賴動態程序集加載,目前有:

Hangfire 用於實現Fire-and-Forgot模式異步執行以及延遲任務;

Protobuf-net 用於存儲到Redis的時候轉Protobuf更快更小。

 

這類程序集有個特色是他要將你要執行的東西序列化爲某種類型(我無論json仍是二進制的信息),而後須要時候在加載程序集。

而他們序列化的時候對程序集的處理通通都是用了Type.AssemblyQualifiedName方法,改方法可能會產生相似「ClassLibrary1.Class1, ClassLibrary1, Version=1.2.0.0, Culture=neutral, PublicKeyToken=null」的字符串。

而咱們本身在CI的時候有一個機制是,每次TFS編譯的時候會自動修改dll的版本號,具體能夠參考之前寫的文章 Azure Devops/Tfs 編譯的時候自動修改版本號

之前.Net Framework加載一個程序集的時候,好比程序集的信息是 「ClassLibrary1.Class1, ClassLibrary1, Version=1.2.0.0, Culture=neutral, PublicKeyToken=null」   其中的Version的值他是不認的,隨便Version是什麼他都能加載(咱不討論StrongName模式)

而到Core以後若是Version不匹配,則會報錯(他會承認Version的值了)

 

解決方案:

暫時去掉了自動修改版本號機制,固定版本號到某個值。

 

3.NetCore下的Redis有點詭異(不穩定)

具體體如今好像遷移到Core以後鏈接Redis的連接更不穩定了,不管是連接超時仍是首次創建連接的成功率都顯著降低。

也是由於這個問題致使此次發佈鬧出了不應有的動靜。

發佈那會的臨時解決方案:

Redis的連接字符串加了,abortConnect=false讓鏈接不上的時候也繼續跑着先吧

進行中的解決方案

根據https://stackoverflow.com/questions/42956377/stackexchange-redis-timeout-exception-in-net-core

試着將代碼內頻繁查詢的Redis讀取轉Async試試。

 

4.NetCore下的Http請求不穩定(時而報SocketException)

到Core以後咱們的未知知識庫裏又新增了一個全新異常模式

image

這個異常看起來像以下幾個地址裏提到的狀況

https://github.com/dotnet/corefx/issues/30691 

https://github.com/dotnet/corefx/pull/32903 

https://github.com/dotnet/corefx/issues/32902

可是要說3.0才fix,等不了那麼久……

 

另外已知在小訪問量下好像不容易出現這個(咱們以前已經有幾個小站點已是core裏可是都沒發生這個問題),有機率跟請求壓力有關係。

 

目前的臨時解決方案

參考官方文檔 https://docs.microsoft.com/en-us/dotnet/api/system.net.http.socketshttphandler?view=netcore-2.2 先將core2.1引入的SocketHttpHandler禁用了

能夠直接Powershell執行

[environment]::SetEnvironmentvariable("DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER", "false", "Machine")  

可是如今也是零星會偶爾冒一下出來(感受並無什麼卵用)

進行中的解決方案

基於HttpClientFactory構造HttpClient外加Polly若是失敗就再來一次的模式。

 

5.迷之超時

如今發覺有一部分機器會有超時的現象,而這個現象比較詭異在於IIS日誌裏是有記錄到此次請求的(超時的請求),而做爲咱們站點監控的Application Insights是沒收到這個請求的

暫時想法是否是由於如今IIS只是一個Reverse Proxy的角色,而IIS到達真正承載站點的kestrel的時候這個過程有問題

image

 

由於咱們當前是基於Net Core 2.1(由於是LTS),並無2.2所引入的進程內託管這種模式,這個問題目前還在定位中

 

另外有人建議(包括網上尋找資料獲得的信息)是IIS裏調整下

Start Mode 改成Always Runing

Idel Time-out Action改成Suspend

可是這都是Win 2012才引入的功能,而咱們家是08R2,兩行淚的羨慕隔壁好多家都是2016的!

 

臨時解決方案:

看到超時的機器就下掉

並且發現這個超時現象主要集中在某幾個服務器上

以後在看看系列的解決方案

後面轉Linux後的話直接kestrel硬扛,IIS一邊去

 

最後

好像在.Net Framework裏常常推崇的在異步方法里加ConfigureAwaiter(false)在.Net Core下是沒什麼卵用的,參考

http://blog.stephencleary.com/2017/03/aspnetcore-synchronization-context.html

相關文章
相關標籤/搜索