每週學點TARS——服務自定義命令

做者 Eatonhtml

導語git

平常開發中,除了基礎的服務管理功能,有時咱們還須要進行一些特殊的業務相關的服務管理,好比清除服務緩存,改變服務的模式、停用服務某個接口等。因爲這些需求和業務耦合性較高,框架層面通常不會提供這樣的功能,開發者甚至須要本身開發額外接口來實現。爲了解決這一問題,TARS 在框架層面提供了自定義命令的功能。github

目錄

  • TARS 自定義命令簡介
  • 添加自定義命令緩存

    • 實現自定義命令響應函數
    • 將響應函數與自定義命令綁定
    • 使用自定義命令
  • TARS 自定義命令的原理
  • 總結

TARS 自定義命令簡介

TARS 自定義命令功能用於實現除框架對服務的基礎管理之外的服務管理功能。開發者可以添加自定義命令並實現命令的邏輯,並經過 TarsWeb 管理頁面來向服務發送命令,觸發自定義命令的邏輯。框架

TARS 服務框架中也經過自定義命令的方式,內置瞭如下八種命令:分佈式

tars.help           # 查看全部管理命令
tars.loadconfig     # 從配置中心, 拉取配置下來: tars.loadconfig filename
tars.setloglevel    # 設置滾動日誌的等級: tars.setloglevel [NONE, ERROR, WARN, DEBUG]
tars.viewstatus     # 查看服務狀態
tars.connection     # 查看當前連接狀況
tars.loadproperty   # 使配置文件的 property 信息生效
tars.setdyeing      # 設置染色信息 tars.setdyeing key servant [interface]

tars.setloglevel 爲例,咱們想要修改某個服務的日誌等級爲 ERROR,打開服務的管理頁面,點擊 更多命令,以下函數

DHJK4e.png

在彈出窗口中選中自定義命令,輸入命令 tars.setloglevel ERROR,並點擊 肯定微服務

DHJUUS.png

點擊 肯定 後,會彈出提示框,提示命令執行結果,以下圖,咱們成功設置了日誌等級。性能

DHYgsI.png

接下來,咱們介紹用戶添加全新自定義命令的方法。ui

添加自定義命令

本部分將以 TarsCpp 應用爲例,介紹如何在服務中添加自定義命令。這裏咱們經過如下命令建立一個服務名爲 CommandDemo.DemoServer.DemoObj 的服務,後面將以該服務爲例子介紹如何使用自定義命令。

/usr/local/tars/cpp/script/cmake_tars_server.sh CommandDemo DemoServer Demo

項目結構以下

DemoServer
├── build                   # 構建目錄
├── CMakeLists.txt          # cmake 構建文件
└── src                     # 源文件目錄
    ├── CMakeLists.txt
    ├── Demo.h              # Demo.tars 生成文件
    ├── DemoImp.cpp         # 接口實現文件
    ├── DemoImp.h           # 接口實現頭文件
    ├── DemoServer.cpp      # 服務實現文件
    ├── DemoServer.h        # 服務實現頭文件
    └── Demo.tars           # tars 接口定義文件
關於 TARS 服務的建立與部署,參考文檔 TARS 服務開發入門,本文再也不贅述。

添加全新自定義命令的方法分兩步:

  1. 實現自定義命令響應函數
  2. 將響應函數與自定義命令綁定

實現自定義命令響應函數

在這一部分中,咱們將嘗試建立並實現一個自定義命令。

首先,咱們在服務實現頭文件 DemoServer.h 中,添加自定義命令函數的聲明

bool testCommand(string const &command, string const &params, string &result);

這裏咱們聲明瞭一個 testCommand 函數。按照自定義命令函數的要求,必須聲明三個參數 command, params, resultcommand 爲具體的指令內容,params 爲自定義命令攜帶的參數,result 爲命令執行的結果,用於返回給 TarsWeb。

而後,咱們在 DemoServer.cpp 中添加這個函數的定義

bool DemoServer::testCommand(string const &command, string const &params, string &result)
{
    RemoteNotify::getInstance()->report("Receive CMD: " + command + " Params: " + params);
    result = "successful";
    return true;
}

實現很是簡單,使用了 RemoteNotify::getInstance()->report() 上報接收到的命令和參數,可以直接在 TarsWeb 接收到上報的信息;並將命令的執行結果信息傳入參數 result,也會在 TarsWeb 中顯示;最後 return true ,表明本次命令執行成功。

將響應函數與自定義命令綁定

最後,咱們在文件 DemoServer.cpp 中服務的初始化函數 DemoServer::initialize 裏,使用 TarsCpp 中提供的宏 TARS_ADD_ADMIN_CMD_NORMAL 來添加自定義命令,以下

void
DemoServer::initialize()
{
    addServant<DemoImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".DemoObj");
    // 添加自定義命令 testCommand
    TARS_ADD_ADMIN_CMD_NORMAL("testCommand", DemoServer::testCommand);
}

TARS_ADD_ADMIN_CMD_NORMAL 第一個參數爲具體命令字符串,即 TarsWeb 中輸入的命令;第二個參數爲命令的觸發函數,即接收到這個命令後會執行的函數,這裏咱們傳入咱們剛剛定義的函數 testCommand

這樣咱們就完成了自定義命令的添加,編譯並在 TarsWeb 發佈服務後,咱們就可以向服務發送自定義命令來管理了。

使用自定義命令

前面咱們已經完成了自定義命令的添加,接下來咱們就可以在 TarsWeb 上向服務發送自定義命令來執行相應的邏輯了。

咱們按照簡介中介紹的方式,在 TarsWeb 的 DemoServer 服務管理頁面中輸入自定義命令。這裏咱們輸入 testCommand param1 param2,即咱們前面添加的命令 testCommand,並附帶了參數,以下圖

點擊 肯定 後,會彈出提示框,提示命令執行結果,以下

[1]: 後面的 successful 即爲前面咱們在自定義命令函數中返回的 result 的值,會顯示在提示框中。而後咱們刷新服務的實時狀態,會出現一條服務狀態信息 ,以下圖

這裏的信息就是函數中調用 RemoteNotify::getInstance()->report() 上報的信息,咱們在函數中上報了命令字符串和傳入的參數字符串,可見,和咱們傳入的是一致的,說明咱們成功執行了自定義命令函數。

TARS 自定義命令的原理

前面咱們瞭解瞭如何添加並向服務發送自定義命令,總結一下流程大體以下:

  1. 聲明並實現自定義命令響應函數;
  2. 將自定義命令與函數綁定。

實際上就是將命令和函數綁定,接收到該命令時執行相應函數。咱們前面提到,命令與函數的綁定經過 TARS_ADD_ADMIN_CMD_NORMAL 實現。它的定義以下

/**
 * 添加Normal命令處理方法
 * 在全部前置方法最後執行
 * 多個Normal方法之間順序不肯定
 */
#define TARS_ADD_ADMIN_CMD_NORMAL(c,f) \
    do { addAdminCommandNormal(string(c), std::bind(&f, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } while (0);

這個宏調用了函數 addAdminCommandNormal 來綁定,再來看看它的定義

void BaseNotify::addAdminCommandNormal(const string& command, TAdminFunc func)
{
    TC_LockT<TC_ThreadRecMutex> lock(*this);

    _procFunctors.insert(std::make_pair(command, func));

    _observer->registerNotify(command, this);
}

從上述代碼中,能夠看出原理很簡單,其實是經過一個 map 類型的對象 _procFunctors 來存儲自定義命令綁定的函數。當調用服務自定義命令入口函數 notify 時,經過這個對象來獲取命令對應的函數,並執行。notify 定義以下

bool BaseNotify::notify(const string& cmd, const string& params, CurrentPtr current, string& result)
{
    TC_LockT<TC_ThreadRecMutex> lock(*this);

    map<string, TAdminFunc>::iterator it;

    it =  _procFunctors.find(cmd);

    if (it != _procFunctors.end())
    {
        return (it->second)(cmd, params, result);
    }
    return false;
}

可見,的確是經過 map 類型對象 _procFunctors 來獲取自定義命令對應的函數的。

總結

本文介紹了 TARS 中的自定義命令功能的使用和原理,經過簡單的使用示例介紹如何使用。開發者也可以根據業務需求,完成更加複雜的操做,實現對服務進行更多管理。

TARS 能夠在考慮到易用性和高性能的同時快速構建系統並自動生成代碼,幫助開發人員和企業以微服務的方式快速構建本身穩定可靠的分佈式應用,從而令開發人員只關注業務邏輯,提升運營效率。多語言、敏捷研發、高可用和高效運營的特性使 TARS 成爲企業級產品。

TARS微服務助您數字化轉型,歡迎訪問:

TARS官網:https://TarsCloud.org

TARS源碼:https://github.com/TarsCloud

Linux基金會官方微服務免費課程:https://www.edx.org/course/bu...

獲取《TARS官方培訓電子書》:https://wj.qq.com/s2/6570357/...

或掃碼獲取:

QR

相關文章
相關標籤/搜索