.NET Core 開車記:Data Protection Key 過時問題與登陸頁面訪問慢

K8s 船還沒修好,.net core 車又出了問題,開着 k8s 豪華郵輪、飈着 .net core 極品飛車的好事真是多磨。數據庫

自從咱們用上 .net core ,就一直被 .net core 的一個慢性病所折磨,這個病叫 Data Protection Key 新陳代謝綜合症,一般3-6個月發做一次。發做時的症狀是新登陸用戶在登陸後依然是未登陸狀態。病因是 Data Protection Key 默認3個月刷新一次,在這個刷新的新陳代謝階段,新舊 key 並存,新的登陸 cookie 用新的 key 進行加密/解密,舊的登陸 cookie 用舊的 key 解密,但有時某種未知狀況會形成新陳代謝時出現功能性紊亂,新 key 加密的 cookie 卻用舊 key 解密失敗,形成解密失敗,登陸 cookie 失效。cookie

昨天下班的時候這個新陳代謝綜合症又發做了,幸虧咱們及時發現,當即採起急救措施,重啓全部應用恢復了正常。在急救時,咱們犯了一個錯,忘了重啓了文件上傳應用,結果形成一段時間沒法上傳圖片。mvc

Keys have a 90-day lifetime by default. When a key expires, the app automatically generates a new key and sets the new key as the active key. As long as retired keys remain on the system, your app can decrypt any data protected with them. (From docs.microsoft.comapp

新陳代謝綜合症急救好以後,開車沒多久,昨天晚上又出現了新的病情,用戶登陸站點突發急性消化不良症,訪問登陸頁面響應速度很慢。排查後發現大量 http get 請求涌向登陸頁面,對應容器的 CPU 佔用一直 150% 左右(平時不到 20%)。雖然源於大量請求,可是讓人想不通的是這個登陸頁面只是顯示一下 mvc 視圖,沒有耗資源的操做,沒有任何數據庫訪問操做,即便這麼大請求也應該能撐住。嘗試給登陸頁面加上 ResponseCache ,問題依舊。嘗試啓動更多容器處理請求,問題依舊。async

進一步排查中發現這個突發急性症狀起源於一篇博文被設置爲登陸後才能訪問,大量訪問這篇博文的請求都跳轉到了登陸頁面(這些請求自己也比較異常,多是機器請求),因而在登陸頁面的 mvc action 中屏蔽這些請求,但病情沒有絲毫改善,這時能夠確認性能瓶頸不在 mvc action 。性能

知道藥用錯地方後,當即跳出當前 mvc action ,放眼整個請求處理管線上的那些 middeware 。望着日誌中不斷出現的大量錯誤,一個 middlware 立馬映入眼簾,它就是用於給 serilog 日誌提供更多上下文信息的 LogEnrichmentMiddleware ,在這個 middleware 中加上屏蔽異常請求的代碼後立馬藥到病除,急性消化不良症就這樣完成了急救。加密

public class LogEnrichmentMiddleware
{
    private static readonly ILogger Logger = Log.ForContext<LogEnrichmentMiddleware>();
    private readonly RequestDelegate _next;

    public LogEnrichmentMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        // 屏蔽異常請求
        if (httpContext.Request.Query.TryGetValue("returnUrl", out var returnUrl) &&
            WebUtility.UrlDecode(returnUrl) == "***")
        {
            httpContext.Response.StatusCode = StatusCodes.Status404NotFound;
            return;
        }

        var properties = new ILogEventEnricher[]
        {
            new PropertyEnricher("RequestUrl", httpContext.Request.GetDisplayUrl()),
            new PropertyEnricher("RequestMethod", httpContext.Request.Method),
            new PropertyEnricher("UserAgent", httpContext.Request.Headers[HeaderNames.UserAgent].ToString()),
            new PropertyEnricher("Ip", httpContext.Connection.RemoteIpAddress.ToString())
        };

        using (LogContext.Push(properties))
        {
            await _next(httpContext);

            var statusCode = httpContext.Response.StatusCode;
            if (statusCode >= 400 && statusCode != 404)
                Logger.Warning("Unsuccessful response {StatusCode}", httpContext.Response.StatusCode);
        }
    }
}

抱歉,這2個問題給您帶來麻煩了,請您諒解。咱們會進一步分析病因,爭取根治這2個病症,讓 .net core 這輛車飈得更穩。spa

相關文章
相關標籤/搜索