搭建前端監控系統(五)Nodejs怎么搭建消息隊列


  怎樣定位前端線上問題,一直以來,都是很頭疼的問題,因為它發生於用戶的一系列操作之后。錯誤的原因可能源於機型,網絡環境,接口請求,復雜的操作行為等等,在我們想要去解決的時候很難復現出來,自然也就無法解決。 當然,這些問題並非不能克服,讓我們來一起看看如何去監控並定位線上的問題吧。 

 

  這是搭建前端監控系統的第五章,主要是介紹如何處理日志高並發上傳的情況,跟着我一步步做,你也能搭建出一個屬於自己的前端監控系統。

  如果感覺有幫助,或者有興趣,請關注 or Star Me 。 

  ============================================================================

  由 www.webfunny.cn 前端監控提供只需要簡單幾步就可以搭建一套屬於自己的前端監控系統,快來試試吧 ^ _ ^

  ============================================================================

  隨着監控日志搜集的內容越來越多,終於有一天,由於公司的一波推文,導致了日志的瞬間流量達到歷史新高,以至於mysql的連接數過多,系統崩潰。 當然,作為日志上傳的服務器,這個是必然會發生的情況,只是早晚的問題。 既然出現了並發問題,那么我們就着手來處理吧。日志上傳如何緩解高並發的情況呢?我們分為三個小點來處理。

  •   增加日志上傳的時間間隔

  正如我們所知,日志上傳的時間間隔越長,用戶在這個間隔內離開的幾率就會越大,日志的漏傳量就會增加,然后會導致日志的准確度降低。因為我們的探針是安插在瀏覽器內的,用戶隨時都有可能關掉,所以,理論上講間隔越短越好,但這並不現實。所以這個需要在服務器的承受能力和日志的准確率之間做個權衡。由具體情況而定

  •   移除探針代碼里冗余的參數,縮短參數名字的長度 

  另外一點,每台服務器的硬盤有限,帶寬有限,如果參數名字太長,參數內容冗余,對服務器的硬盤和帶寬都是一種極大的浪費。雖然每條日志都不起眼,但是日志起量了以后,就是會是一筆非常龐大的開銷。

  •   Nodejs + RabbitMq 搭建消息隊列,緩解瞬間並發量  

  對於一個前端來說,要把消息隊列搭建起來還確實費了一番周折。 

  1)  ubantu16 安裝RabbitMQ服務軟件包,很多教程都要求安裝erlang, 但是更新apt以后,直接執行安裝命令,會自動安裝erlang的核心組件的。(erlang始終無法成功安裝,真心累。)

$ apt-get update
$ apt-get install rabbitmq-server // 安裝
$ rabbitmq-plugins enable rabbitmq_management // 啟動插件,瀏覽器才能訪問

  正常情況下是直接成功的,直接訪問ip端口號就可以打開了 http://IP:15672, 如下圖:

  2)現在我們需要一個有效的登錄名和密碼,執行如下命令

$ rabbitmqctl add_user username password  // 設置用戶名密碼
$ rabbitmqctl set_user_tags username administrator  // 設置為管理員身份
$ rabbitmqctl set_permissions -p / username ".*" ".*" ".*"  //為用戶設置讀寫等權限 

  OK, 現在我們登錄進來就是這樣的界面,如此消息隊列服務我們算是搭建完成了。

  3)消息服務啟動了,那么如何存消息,如何取消息呢?如下圖所示:

  

  我能夠接觸到的關於消息隊列的應用場景實在有限,所以不能介紹更復雜的內容,大致的思維邏輯如上圖1:有消息進來,先存入消息隊列里,另一端再從隊列去取出來,完成接下來的工作。從代碼的角度來看如上圖2:就是一個生產者和消費者的模式,生產者不停的向消息隊列里生產消息,消費者在有需要的時候,從消息隊列里取消息, 一旦完成消費,隊列里便移除這個消息。消息的生產者和消費者互相沒有感知,生產者產生過剩的消息都存放在消息隊列里,由消費者慢慢消耗。以此來削峰填谷,達到處理高並發的目的。當然這都是我的淺顯理解,但是也足以滿足目前日志上傳的需求了。

  OK、理論說完了,具體如何實現呢?

  

let amqp = require('amqplib');

module.exports = class RabbitMQ {
  constructor() {
    this.hosts = ["amqp://localhost"]; 
    this.index = 0;
    this.length = this.hosts.length;
    this.open = amqp.connect(this.hosts[this.index]);
  }
 // 消息生產者
  sendQueueMsg(queueName, msg, errCallBack) {
    let self = this;
    self.open
      .then(function (conn) {
        return conn.createChannel();
      })
      .then(function (channel) {
        return channel.assertQueue(queueName).then(function (ok) {
          return channel.sendToQueue(queueName, new Buffer.from(msg), {
            persistent: true
          });
        })
          .then(function (data) {
            if (data) {
              errCallBack && errCallBack("success");
              channel.close();
            }
          })
          .catch(function () {
            setTimeout(() => {
              if (channel) {
                channel.close();
              }
            }, 500)
          });
      })
      .catch(function () {
      // 這里嘗試備用連接,我就一個,所以就處理了
      });
  }
 
// 消息消費者 receiveQueueMsg(queueName, receiveCallBack, errCallBack) { let self = this; self.open.then(function (conn) { return conn.createChannel(); }).then(function (channel) { return channel.assertQueue(queueName).then(function (ok) { return channel.consume(queueName, function (msg) { if (msg !== null) { let data = msg.content.toString(); channel.ack(msg); receiveCallBack && receiveCallBack(data); } }).finally(function () { }); }) }) .catch(function (e) { errCallBack(e) }); } }

 

消息隊列測試:每隔5秒發送一條消息,每隔5秒取出一條消息,成功

var mq = new RabbitMQ()
setInterval(function () {
  mq.sendQueueMsg("queue1", "這是一個隊列消息", function (err) {
    console.log(err)
  })
}, 5000)

setInterval(function () {
  mq.receiveQueueMsg("queue1", function (msg) {
    console.log(msg)
  }, function (error) {
    console.log(error)
  })
}, 5000)

 

RabbitMq消息隊列使用中遇到的坑:

①   var mq = new RabbitMQ() 多次創建RabbitMQ對象,導致connections, channels, memory 暴增,服務器很快掛掉

②  生產者的channel忘記close, 導致channel太多,服務器超負荷

③   消費者的channel被close掉了,永遠只能接收到一條消息,消息隊列很快爆掉

最后是消息隊列運行的狀態:

 

OK、經過了這么一番處理,我們的日志上傳應該能夠承受住一定量的並發了,讓我們拭目以待吧。

 

上一章:搭建前端監控系統(四)接口請求異常監控篇

 

參考: 架構設計之NodeJS操作消息隊列RabbitMQ  Ubuntu上安裝和使用RabbitMQ


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM