<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

        公司使用了阿里云的服務(wù),其中可以在項(xiàng)目中使用全鏈路監(jiān)測(cè),最近要排查慢響應(yīng),所以就在 Node 項(xiàng)目中接了一下 SkyWalking

        本文還會(huì)記錄在使用時(shí)遇到的問(wèn)題,以及解決思路。

      一、初始化

      1)參數(shù)配置

        SkyWalking支持自動(dòng)埋點(diǎn)和手動(dòng)埋點(diǎn),自動(dòng)埋點(diǎn)只要初始化后,就可以開(kāi)始工作,很便捷。

        

      2)下載依賴

        下載 SkyWalking Node.js Agent

      npm install --save skywalking-backend-js

      3)初始化

        在項(xiàng)目的 app.js 中配置和啟用 SkyWalking。

      const {default: agent} = require("skywalking-backend-js");
      
      agent.start({
          serviceName: 'web-api-pro',
          collectorAddress: 'xxx',       
          authorization: 'xxx'
      });

      二、分析

      1)應(yīng)用概覽

        在應(yīng)用列表,選擇web-api進(jìn)入后,就能看到如下的分析頁(yè)面。

        

        SkyWalking默認(rèn)會(huì)上報(bào)項(xiàng)目?jī)?nèi)的所有接口通信、MySQL查詢、MongoDB查詢等。

        但這樣會(huì)增加存儲(chǔ)成本,所以我需要將不相關(guān)的接口過(guò)濾去除。

      2)過(guò)濾接口

        翻閱官方文檔,發(fā)現(xiàn)有個(gè)參數(shù)有這個(gè)過(guò)濾作用,字符串類型,默認(rèn)是空字符串。

      SW_TRACE_IGNORE_PATH The paths of endpoints that will be ignored (not traced), comma separated ``

        而跳轉(zhuǎn)到源碼中,也發(fā)現(xiàn)了對(duì)應(yīng)的字段:traceIgnorePath。

      export declare type AgentConfig = {
          serviceName?: string;
          collectorAddress?: string;
          authorization?: string;
          ignoreSuffix?: string;
          traceIgnorePath?: string;
          reIgnoreOperation?: RegExp;
      };

        在 deepseek 上提問(wèn),AI 給了我如何使用參數(shù)的示例,通配符的作用也詳細(xì)的說(shuō)明了。

      traceIgnorePath: "/healthcheck/*,/static/**"

        但是,提交到測(cè)試環(huán)境后,并沒(méi)有像預(yù)想的那樣,將指定路徑的接口過(guò)濾掉。

        在將配置路徑,翻來(lái)覆去的更改后,仍然不見(jiàn)效,遂去查看源碼,在源碼中的確包含 traceIgnorePath 參數(shù)。

      3)求助阿里云

        由于這是阿里云提供的可選類型,所以就去阿里云上創(chuàng)建工單。

        

        馬上就自動(dòng)創(chuàng)建了一個(gè)小群,與對(duì)方的人員語(yǔ)音溝通了下,并且共享了屏幕代碼。

        他表示需要花點(diǎn)時(shí)間,自己操作一下,在此期間,我自己也繼續(xù)查看源碼,最終發(fā)現(xiàn)了端倪。

        阿里云的響應(yīng)還是很快的,特別及時(shí)。

      4)源碼分析

        在 node_modules 目錄中的文件,也可以打印日志,我將傳入的參數(shù)都打印了出來(lái)。

      serviceName: 'web-api',
      serviceInstance: 'MacBook-Pro.local',
      collectorAddress: 'xxxx',
      authorization: 'xxxx',
      ignoreSuffix: '.gif',
      traceIgnorePath: '/audiostream/audit/callback',
      reIgnoreOperation: /^.+(?:\.gif)$|^(?:\/audiostream\/audit\/callback)$/,

        看到 reIgnoreOperation 參數(shù)被賦值了,一段正則,這個(gè)很關(guān)鍵,過(guò)濾接口,其實(shí)就是匹配正則。

        用 reIgnoreOperation 搜索,搜到了被使用的一段代碼,operation 是一個(gè)傳遞進(jìn)來(lái)的參數(shù)。

      SpanContext.prototype.ignoreCheck = function (operation, type, carrier) {
       if (operation.match(AgentConfig_1.default.reIgnoreOperation) || 
          (carrier && !carrier.isValid()))
          return DummySpan_1.default.create();
        return undefined;
      };

        然后再用用 traceIgnorePath 去搜索代碼,并沒(méi)有得到有用的信息,于是將關(guān)鍵字改成 Ignore。

        

        果然找到了合適的代碼,在 HttpPlugin.prototype.interceptServerRequest 方法中,找到一段創(chuàng)建 span 的代碼。

      var operation = reqMethod + ':' + (req.url || '/').replace(/\?.*/g, '');
      var span = AgentConfig_1.ignoreHttpMethodCheck(reqMethod)
         ? DummySpan_1.default.create()
         : ContextManager_1.default.current.newEntrySpan(operation, carrier);

        鏈路(即鏈路追蹤)可深入了解請(qǐng)求路徑、性能瓶頸和系統(tǒng)依賴關(guān)系,多個(gè)處理數(shù)據(jù)的片段(也叫 span,跨度)通過(guò)鏈路 ID 進(jìn)行串聯(lián),組成一條鏈路追蹤。

        span 中有個(gè)三目運(yùn)算,經(jīng)過(guò)測(cè)試發(fā)現(xiàn),如果沒(méi)有配置要過(guò)濾的請(qǐng)求方法,那么就是 false。

        所以會(huì)進(jìn)入到 newEntrySpan() 方法中,而在此方法中,恰恰會(huì)調(diào)用 ignoreCheck() 方法。

        那么其傳入的 operation,其實(shí)就是要匹配的路徑值,原來(lái)我配錯(cuò)了,官方需要帶請(qǐng)求方法,如下所示。

      traceIgnorePath: 'POST:/audiostream/audit/callback',

        不要過(guò)渡依賴 AI,我這次就非常相信 AI 給的示例,結(jié)果繞了大彎。

      5)運(yùn)行原理

        在執(zhí)行 start() 方法時(shí),會(huì)進(jìn)行參數(shù)合并,參數(shù)修改等操作。

      Agent.prototype.start = function (options) {
        // 傳入?yún)?shù)和默認(rèn)參數(shù)合并
        Object.assign(AgentConfig_1.default, options);
        // 初始化參數(shù),例如拼接正則等
        AgentConfig_1.finalizeConfig(AgentConfig_1.default);
        // 掛載插件,就是注入鏈路代碼
        new PluginInstaller_1.default().install();
        // 上報(bào)
        this.protocol = new GrpcProtocol_1.default().heartbeat().report();
        this.started = true;
      };

        其中在 report() 中,會(huì)創(chuàng)建一個(gè)定時(shí)任務(wù),每秒運(yùn)行一次。

      setTimeout(this.reportFunction.bind(this), 1000).unref();

        .unref() 告訴 Node.js 事件循環(huán):“此定時(shí)器不重要,如果它是唯一剩余的任務(wù),可以忽略它并退出進(jìn)程”。

        優(yōu)化進(jìn)程生命周期管理,避免無(wú)關(guān)任務(wù)阻塞退出。

        最核心的插件有HttpPlugin、IORedisPlugin、MongoosePlugin、AxiosPlugin、MySQLPlugin 等。

        以 HttpPlugin 為例,在 install() 時(shí),會(huì)調(diào)用 interceptServerRequest() 方法注入鏈路操作。

      HttpPlugin.prototype.install = function () {
        var http = require('http');
        this.interceptServerRequest(http, 'http');
      };

        在 interceptServerRequest() 中,會(huì)修改 addListener()、on() 方法,并且會(huì)包裝響應(yīng)。

      HttpPlugin.prototype.interceptServerRequest = function (module, protocol) {
        var plugin = this;
        var _addListener = module.Server.prototype.addListener;
        module.Server.prototype.addListener = module.Server.prototype.on = 
        function (event, handler) {
          var addArgs = [];
          // 復(fù)制參數(shù)
          for (var _i = 2; _i < arguments.length; _i++) {
            addArgs[_i - 2] = arguments[_i];
          }
          // 執(zhí)行事件
          return _addListener.call.apply(
             _addListener, 
             tslib_1.__spreadArrays([this, event, 
               event === 'request' 
               ? _sw_request 
               : handler
             ], 
             addArgs)
          );
          function _sw_request(req, res) {
             var _this = this;
             var _a;
             var reqArgs = [];
             // 復(fù)制參數(shù)
             for (var _i = 2; _i < arguments.length; _i++) {
               reqArgs[_i - 2] = arguments[_i];
             }
             var carrier = ContextCarrier_1.ContextCarrier.from(req.headers || {});
             var reqMethod = (_a = req.method) !== null && _a !== void 0 ? _a : 'GET';
             // 拼接請(qǐng)求方法和接口路徑
             var operation = reqMethod + ':' + (req.url || '/').replace(/\?.*/g, '');
             var span = AgentConfig_1.ignoreHttpMethodCheck(reqMethod)
                 ? DummySpan_1.default.create()
                 : ContextManager_1.default.current.newEntrySpan(operation, carrier);
             span.component = Component_1.Component.HTTP_SERVER;
             span.tag(Tag_1.default.httpURL(protocol + '://' + (req.headers.host || '') + req.url));
             // 包裝響應(yīng)信息
             return plugin.wrapHttpResponse(span, req, res, function () { 
               return handler.call.apply(
                  handler, 
                  tslib_1.__spreadArrays([_this, req, res], reqArgs)
               ); 
             });
           }
         };
      };

        不過(guò)在上線后,發(fā)生了意想不到的意外,就是原先可以鏈?zhǔn)秸{(diào)用的 Mongoose 的方法:

      this.liveApplyRecord.find({ userId }).sort({ createTime: -1 });

        在調(diào)用時(shí)會(huì)出現(xiàn)報(bào)錯(cuò):

      this.liveApplyRecord.find(...).sort is not a function

       

       posted on 2025-07-16 11:01  咖啡機(jī)(K.F.J)  閱讀(308)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 亚洲欧美日韩在线码| 国产亚洲999精品AA片在线爽| 成人特黄A级毛片免费视频| 亚洲欧美人成人综合在线播放 | 国产精品白丝久久av网站| 亚洲色av天天天天天天| 亚洲偷自拍另类一区二区| 国产高清一区二区不卡| 在线看无码的免费网站| 午夜激情小视频一区二区| 国产精品久久久午夜夜伦鲁鲁| 亚洲免费人成视频观看| 99久久国产露脸国语对白| 国产av丝袜熟女一二三| 东乌| 高清在线一区二区三区视频| 国产va免费精品观看| 国产精品久久一区二区三区| 亚洲国产一成人久久精品| 国产天美传媒性色av| 连平县| 午夜一区二区三区视频| 曰韩亚洲AV人人夜夜澡人人爽| 国产av午夜精品福利| 永久不封国产av毛片| 日韩AV无码精品一二三区| 武陟县| 国产亚洲精品成人aa片新蒲金 | 色综合天天综合天天综| 国内精品久久久久久久coent| 国产精品毛片一区二区| 高中女无套中出17p| 精品无码中文视频在线观看| 国产成人亚洲精品自产在线| 日韩加勒比一本无码精品| 亚洲高潮喷水无码AV电影| 亚洲成人av在线资源网| 亚洲a免费| 国产精品毛片在线看不卡| 国产又色又爽无遮挡免费动态图| 国产不卡在线一区二区|