最近將本身負責的一個核心接口系統從.Net Framework遷移到了.Net Core。html
總體過程,從業務層面說通常般吧(總體還好但仍是搞的業務有感,沒出嚴重故障)可是技術層面上感受其實並無達到要求,不過預期也是應該不會那麼順利,接下來可能還須要幾個小Fix來處理各類奇奇怪怪的問題。git
回顧下遷移時候遇到的若干個坑,但願對後續有此類操做的人全部幫助。github
咱們回顧下在Web Api裏時候的一個路由定義redis
這個配置下可讓shell
Get RootUrl/123 和 Get 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)。異步
①強制在方法參數的id里加上[FromQuery],可是這個會有個咖喱是Swagger生成的文檔裏會有2個Id字段(Path裏有一個,你強制了Query裏有一個)可是接口能正常工做;socket
②將2個路由拆開來分別對應2個方法。
總結:
按照咱們組內規範,定義Url是不能放Path的,這些都是一些早期設計的,沒有遵守規範將其替換完一直遺留着,規範不嚴格,代碼兩行淚。
咱們有使用到部分的類庫會依賴動態程序集加載,目前有:
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的值了)
暫時去掉了自動修改版本號機制,固定版本號到某個值。
具體體如今好像遷移到Core以後鏈接Redis的連接更不穩定了,不管是連接超時仍是首次創建連接的成功率都顯著降低。
也是由於這個問題致使此次發佈鬧出了不應有的動靜。
Redis的連接字符串加了,abortConnect=false讓鏈接不上的時候也繼續跑着先吧
根據https://stackoverflow.com/questions/42956377/stackexchange-redis-timeout-exception-in-net-core
試着將代碼內頻繁查詢的Redis讀取轉Async試試。
到Core以後咱們的未知知識庫裏又新增了一個全新異常模式
這個異常看起來像以下幾個地址裏提到的狀況
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若是失敗就再來一次的模式。
如今發覺有一部分機器會有超時的現象,而這個現象比較詭異在於IIS日誌裏是有記錄到此次請求的(超時的請求),而做爲咱們站點監控的Application Insights是沒收到這個請求的
暫時想法是否是由於如今IIS只是一個Reverse Proxy的角色,而IIS到達真正承載站點的kestrel的時候這個過程有問題
由於咱們當前是基於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