每周学点TARS——服务自定义命令

TARS基金会

作者 Eaton

导语

日常开发中,除了基础的服务管理功能,有时我们还需要进行一些特殊的业务相关的服务管理,比如清除服务缓存,改变服务的模式、停用服务某个接口等。由于这些需求和业务耦合性较高,框架层面一般不会提供这样的功能,开发者甚至需要自己开发额外接口来实现。为了解决这一问题,TARS 在框架层面提供了自定义命令的功能。

目录

  • 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

接下来,我们介绍用户添加全新自定义命令的方法。

添加自定义命令

本部分将以 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

阅读 1.2k

2020年3月10日,Linux基金会正式宣布旗下的TARS开源项目将成立TARS基金会。TARS基金会是一个专注于微服...

16 声望
7 粉丝
0 条评论

2020年3月10日,Linux基金会正式宣布旗下的TARS开源项目将成立TARS基金会。TARS基金会是一个专注于微服...

16 声望
7 粉丝
文章目录
宣传栏