前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >腾讯 Tars 基础框架手动搭建——填掉官方 Guide 的坑

腾讯 Tars 基础框架手动搭建——填掉官方 Guide 的坑

原创
作者头像
amc
修改2019-11-08 12:23:46
24.6K18
修改2019-11-08 12:23:46
举报
文章被收录于专栏:后台全栈之路后台全栈之路

背景

Tars 简介

腾讯 Tars 是腾讯内部使用的 TAF(Tencent Application Framework)的对外开源版,去掉了许多冗杂多余的部分。该框架集开发、运维、微服务、RPC 等为一体。对程序员而言,这就是一个能够快速搭建整个微服务体系的开发框架。这个框架支持基于 C++Node.jsPHPJava 等语言开发,最新版本已经支持后台开发语言新贵——Go

本系列文章:

安装任务

Tars 实际的应用场景是多机器、多节点部署的,不过从实验验证的角度,我做的只是在单一一台机器上,实现 Tars 管理平台部署,以及任务的发布。由于 Tars 版本一直在迭代,为防止文章过时误导后来者,本文以 f3ef251013 节点为准,请读者 follow 最新的 Tars 版本来。官方安装文档在这里

然而,正如很多新的开源项目一样,代码很丰满,文档很骨感。一步一步跟着官方文档走的话,是有可能无法一次走通的……本文跟随文档的安装脉络,进行了重新梳理,为读者呈现一个尽量不挖坑的搭建过程。

请注意,“Tars” 这个概念,除了其基础框架之外,还包含开发工具(如 TarsCpp、TarsJava 等等)、协议等等许多内容。不过本文主要讲述 Tars 基础框架,因此下文所提及的 “基础框架”,如无特别说明,都专指 “Tars 基础框架”。

本文解决的问题

前文提及,直接 follow 官方文档,是无法完成服务部署的。因为过程中遇到很多坑,每一个坑都导致基础框架无法搭建,或者是搭建后无法发布服务。笔者根据文档搭建过程中遇到的坑有:

  • 部分操作需要 sudo——文档中有些温馨地提醒了 sudo,但是另外一些未提醒
  • 数据库采用 MySQL 5.6 版,但部分说明不适用于 MariaDB
  • 说明文字与配图不完全一致
  • 不同代码处的数据库用户名和密码不统一
  • 启动所需的数据库表信息有缺失

环境准备

系统准备

部署实验需要准备至少一台 Linux 机器。这可以是一台本地的实体机或虚拟机,也可以是一台云主机。由于部署过程中,需要编译 Tars 框架以及 MySQL 代码(如果系统里没装 Oracle 的 MySQL 的话),强烈建议系统至少要求有 4GB 的内存!系统建议采用 CentOS 或 Ubuntu。本文采用 Ubuntu 来安装,但 CentOS 差别不大,读者可以参考执行。

此外,笔者不采用 root 账户,只有在需要 root 权限的时候才使用 sudo 操作。

像笔者这样只有 1 核 1GB 云主机的,还需要在本地额外准备一台 Linux 虚拟机用于编译,再将编译出来的目标文件转移到云主机上。

软件准备

使用 Ubuntu,基础框架和 C++ 开发环境需要以下开发组件:

代码语言:txt
复制
gcc g++(CentOS 则是 gcc-c++) flex bison make cmake perl gcc zlibc gzip git libncurses5-dev
protobuf-c-compiler protobuf-compiler libprotobuf-dev libprotobuf-c-dev libprotoc-dev
libmariadb-client-lgpl-dev mariadb-client mariadb-server

此外,还需要手动安装的软件或库有:

代码语言:txt
复制
mysql-server node.js(包括 npm)
TarsCloud/TarsFramework TarsCloud/TarsWeb TarsCloud/TarsCpp

这些手动安装的软件会在后问说明。

MySQL 问题

官方文档使用的 MySQL 版本是 5.6。但是这有两个问题:

  1. Oracle 维护的开源 MySQL 已经发展到 5.7 和 8.0 版了,Tars 是否向后兼容?
  2. 最新的 CentOS 和 Ubuntu 的软件包中已移除 MySQL,以 MariaDB 取代,Tars 是否支持?

本人的答案是:

  1. 网上的资料看,基础框架支持 5.7,但需要修改 cmake 的选项,麻烦点;此外,在交流群中也有反馈 5.7 版有问题,但没有深入了解。
  2. 支持,详见后文操作。

笔者的方案是:

  • 使用 mariadb 作为数据库
  • 使用 libmysqlclient.a 作为 TarsCpp 开发环境创建时链接的库(基础框架编译时强制链接静态库)
  • 使用 libmariadb.so 作为实际应用开发时用的库

备份

安装之前,强烈建议不熟悉 Tars 基础框架的读者先给自己的机器做下备份,比如打个快照或者做个镜像之类的,这样如果后面部署失败了,也便于回滚系统,而不是一个一个抓虫。


安装支持软件

笔者所使用的用户名是 ubuntu,后文会有一些 shell 命令中采用了这个用户名,请读者留意替换成为自己的用户名。

MySQL

安装路径准备

默认下载的 Tars 基础框架需要链接 MySQL 的静态库 libmysqlclient.a,此外对库所在的位置也写死在了 Makefile 中。因此我们需要为 Tars 基础框架准备环境。

首先创建供基础框架链接的路径:

代码语言:txt
复制
$ sudo mkdir -p /usr/local/mysql
$ sudo chown ubuntu:ubuntu /usr/local/mysql

然后需要寻找一下 mariadb 的动态库位置和头文件位置:

代码语言:txt
复制
$ sudo find / -name 'mariadb_com.h' 2>/dev/null
$ sudo find / -name 'libmariadbclient*' 2>/dev/null

笔者的环境中,两者分别在 /usr/include/mariadb/usr/lib/x86_64-linux-gnu 下,那么我们就创建两个软链接:

代码语言:txt
复制
$ ln -s /usr/include/mariadb /usr/local/mysql/include
$ ln -s /usr/lib/x86_64-linux-gnu /usr/local/mysql/lib

再创建一个目录给 MySQL 实际安装用:

代码语言:txt
复制
$ mkdir /home/ubuntu/mysql-5.6			# /home/ubuntu 是笔者系统的家目录,读者请注意替换。以下同理。

编译安装

直接从 GitHub 上 clone MySQL 的工程代码后,选择合适的版本:

代码语言:txt
复制
$ mkdir -p ~/github.com/mysql/mysql-server
$ cd ~/github.com/mysql/mysql-server
$ git clone https://github.com/mysql/mysql-server.git ./
$ git checkout -b 5.6 origin/5.6			# 切换到 5.6 版

配置、编译、安装:

代码语言:txt
复制
$ cmake . -DCMAKE_INSTALL_PREFIX=/home/ubuntu/mysql-5.6 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DMYSQL_USER=mysql -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DDOWNLOAD_BOOST=1 -DWITH_BOOST=/home/ubuntu/others/boost
$ make && make install

通过之后,我们还需要将 mysql 的静态库复制(或者链接)到为 Tars 基础框架准备的目录下:

代码语言:txt
复制
$ ln -s /home/ubuntu/mysql-5.6/libmysqlclient.a /usr/local/mysql/lib/

Node.js

Tars 管理平台是使用 node.js 开发的,因此需要安装 nvm。对不熟悉 node 的读者,这里也简单列下安装方式(不建议使用 root 账户操作):

代码语言:txt
复制
$ wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
$ source ~/.bashrc
$ nvm install v8.11.3
$ npm install -g pm2 --registry=https://registry.npm.taobao.org

Tars 基础框架

首先,要下载 Tars 的基础框架代码:

代码语言:txt
复制
$ mkdir -p /home/ubuntu/github.com/TarsCloud/TarsFramework
$ cd /home/ubuntu/github.com/TarsCloud/TarsFramework
$ git clone https://github.com/TarsCloud/TarsFramework.git ./

编译之:

代码语言:txt
复制
$ cd build
$ chmod +x build.sh
$ ./build.sh prepare
$ ./build.sh all

如果编译失败(一般是缺某些库或组件),建议在解决问题后,清掉 TarsFramework 下的所有文件,重新 clone 后再编译。

安装的过程复杂一点,安装路径是固定的(虽然可以在工程文件中调整,为统一起见,不建议修改):

代码语言:txt
复制
$ sudo mkdir -p /usr/local/tars
$ sudo mkdir -p /home/tarsproto/protocol
$ sudo chown ubuntu:ubuntu /usr/local/tars /home/tarsproto/protocol
$ cd /home/ubuntu/github.com/TarsCloud/TarsFramework/build
$ ./build.sh install

准备 Tars 数据库

Tars 使用用户名 tars、密码 tars2015 的组合,操作 MySQL 数据库。高级玩法自然是修改 Tars 中的用户名/密码组合。这里为了简单起见,干脆就直接采用默认的就好了。不过后文会介绍如何使用自定义的用户名密码。

笔者做验证时的 MySQL 与 Tars 部署在同一台机器上,IP 地址是 172.19.16.13。实际部署中,读者请注意换成实际地址。

添加相关账户的命令如下:

代码语言:txt
复制
$ mysql -u root -p

进入 mysql 命令行后:

代码语言:txt
复制
MariaDB [(none)]> grant all privileges on *.* to tars@'%' identified by 'tars2015';
MariaDB [(none)]> flush privileges;
MariaDB [(none)]> exit;

官方文档说的配置备份什么的,就不用关心了。使用 Tars 的系统基本是部署在云上的,大都会用云服务商提供的自带主备的数据库服务(推荐腾讯云 TDSQL 哦,金融级 DB,但是价格和普通 DB 一个等级)。

接下来,我们通过执行 Tars 基础框架的 sql 脚本来创建相应的数据库结构:

代码语言:txt
复制
$ cd /home/ubuntu/github.com/TarsCloud/TarsFramework/sql/
$ sed -i "s/192.168.2.131/${MAIN_HOST}/g" `grep 192.168.2.131 -rl ./*`
$ sed -i "s/db.tars.com/${DB_HOST}/g" `grep db.tars.com -rl ./*`
$ sed -i "s/10.120.129.226/${DB_HOST}/g" `grep 10.120.129.226 -rl ./*`
$ sed -i "s/uroot/utars/g" exec-sql.sh
$ sed -i "s/proot@appinside/ptars2015/g" exec-sql.sh

其中,${DB_HOST} 是预备给 tars 基础框架使用的 DB 的 IP 地址或者域名,读者实际部署时请注意修改;${MAIN_HOST} 是主控的地址,在本文的情况下,也就是当前部署 Tars 基础框架的地址(不要用 127.0.0.1

接着,我们需要修改一下 exec-sql.sh 文件中的 mysql 命令,因为那些命令中并没有指定数据库的 host。修改完后,我们再执行这个 sql 命令

代码语言:txt
复制
$ sed -i "s/mysql/mysql -h${DB_HOST}/g" exec-sql.sh
$ chmod +x exec-sql.sh
$ ./exec-sql.sh

TIPS-1

如果读者不使用 tars/tars2015 的用户名/密码组合来操作数据库,那么可以自行修改上述的 sql 脚本:

代码语言:txt
复制
$ cd /home/ubuntu/github.com/TarsCloud/TarsFramework/sql/
$ git status .
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   db_tars.sql
	modified:   exec-sql.sh
	modified:   tarsconfig.sql
	modified:   tarslog.sql
	modified:   tarsnotify.sql
	modified:   tarspatch.sql
	modified:   tarsproperty.sql
	modified:   tarsqueryproperty.sql
	modified:   tarsquerystat.sql
	modified:   tarsstat.sql

可以看到被 sed 语句修改了的文件。读者可以在这些文件中找到用户名和密码配置项进行修改后,再执行。

TIPS-2

MariaDB server 安装之后默认监听 127.0.0.1 地址,但官方文档明确说明 DB 的 IP 地址不能使用 127.0.0.1。读者需要修改 MariaDB 的配置文件中监听地址的选项,否则后续 Tars 基础框架启动后,会遇到没有权限访问数据库的错误。

Ubuntu 的 MariaDB 的配置地址实际上是 /etc/mysql/mariadb.conf.d/50-server.cnf


部署 Tars 基础框架

Tars 框架核心服务

Tars 核心基础框架指的是 tarsAdminRegistry, tarsregistry, tarsnode, tarsconfig, tarspatch 五个。前面我们其实已经编译好了,我们可以先把这些服务打包:

代码语言:txt
复制
$ cd /home/ubuntu/github.com/TarsCloud/TarsFramework/build
$ make framework-tar

这会在 build 目录下生成 framework.tgz 文件。接下来我们需要做一些操作:

代码语言:txt
复制
$ sudo mkdir -p /data/log/tars
$ sudo mkdir -p /home/tarsproto
$ sudo mkdir -p /usr/local/app/tars
$ sudo chown -R ubuntu:ubuntu /usr/local/app /data/log/tars /home/tarsproto
$ mv /home/ubuntu/github.com/TarsCloud/TarsFramework/build/framework.tgz /usr/local/app/tars
$ cd /usr/local/app/tars
$ tar zxvf framework.tgz

这会在 /usr/local/app/tars/ 下面生成前述几个核心基础框架组件对应的文件夹。此外,还有 tars_install.shtarsnode_install.sh 两个脚本。不过我们得先配置一下——

五个核心基础框架组件的目录下均有 conf 文件夹,可以看到各个组件的配置文件,比如 tars.tarsregistry.config.conf。对操作已经很熟悉了的读者可以手动修改这些配置。不过也可以简单点地进行以下修改:

代码语言:txt
复制
$ cd /usr/local/app/tars
$ sed -i "s/192.168.2.131/${LOCAL_HOST}/g" `grep 192.168.2.131 -rl ./*`
$ sed -i "s/db.tars.com/${DB_HOST}/g" `grep db.tars.com -rl ./*`
$ sed -i "s/registry.tars.com/${MAIN_HOST}/g" `grep registry.tars.com -rl ./*`
$ sed -i "s/web.tars.com/${MAIN_HOST}/g" `grep web.tars.com -rl ./*`

四个 sed 命令修改的地址,对应的是:

  1. 本机地址,不能写 127.0.0.1
  2. 前述数据库的地址;
  3. tarsregistry 的 部署地址,也就是主控的部署地址;
  4. web.tars.comrsync 服务和 web 管理平台的部署地址,本文和主控部署在同一机器上。

修改了地址之后,还需要检查 tars 访问数据库的用户名和密码。这里我们最好是手动 vim 去改,因为几个文件的书写格式不完全一致:

代码语言:txt
复制
$ cd /usr/local/app/tars
$ grep dbpass -rl ./*

检查搜索出来的 conf 文件中的 dbuserdbpass 字段。

最后就是启动核心框架服务和 rsync(好艰难):

代码语言:txt
复制
$ cd /usr/local/app/tars
$ chmod +x tars_install.sh
$ ./tars_install.sh
$ sudo ./tarspatch/util/init.sh
$ chmod +x tarsnode_install.sh
$ ./tarsnode_install.sh

然后我们可以在 crontab 中配置核心基础框架的监控项,这里建议用 sudo 操作:

代码语言:txt
复制
* * * * * /usr/local/app/tars/tarsnode/util/monitor.sh

这样一来,五个框架核心服务就启动起来了。

Tars web 管理平台

Tars web 管理系统在另一个 Git repo 中:

代码语言:txt
复制
$ mkdir -p /home/ubuntu/github.com/TarsCloud/TarsWeb
$ cd /home/ubuntu/github.com/TarsCloud/TarsWeb
$ git clone https://github.com/TarsCloud/TarsWeb.git ./
$ sed -i 's/db.tars.com/${DB_HOST}/g' config/webConf.js
$ sed -i 's/registry.tars.com/${MAIN_HOST}/g' config/tars.conf

其中 ${DB_HOST} 是数据库的 IP 或域名;${MAIN_HOST} 则是主控的地址,在本文的情况下,也就是当前部署 Tars 基础框架所用的 IP 地址(不要使用 127.0.0.1

TIPS:

  • Tars web 是用 node.js 编写的,不需要编译。管理平台默认监听在 3000 端口上,可在 config/webConf.js 中修改 port 参数的值。
  • 如果按照前面所提及的,需要修改 Tars 基础框架访问 DB 的用户名 / 密码,那么请查看一下 config.webConf.js 文件,数据库相关的配置都在最前面。

配置了端口之后,就可以启动 Tars web 管理平台了:

代码语言:txt
复制
$ cd /home/ubuntu/github.com/TarsCloud/TarsWeb
$ npm install --registry=https://registry.npm.taobao.org
$ npm run prd

可以查看 TarsWeb 目录下的 package.json 文件可以看到更多的信息——毕竟并不是每个人都懂得 node.js 开发。

Tars 框架基础服务

检查核心服务状态

Tars web 管理平台启动后,如果按照默认设置的话,平台会在 3000 端口建立 http 服务。使用浏览器访问,可以看到如下界面:

这三个组件,就是前文所述的 “tars 框架核心服务” ,如果按照前述逻辑部署后,在 web 页面就可以看到的。可以依次点开这三个服务,确保服务的状态都如下图所示:

如果服务的状态不对,那么可能是前面哪一步操作不恰当。可以查找 log 来定位(log 文件的路径参见后文)。

部署其他基础服务

剩下的几个基础框架服务就需要进行手动部署。但部署的方法其实还是蛮简单的,这里挑一个出来细讲,其他的类似。

首先,我们需要把其他的基础框架打包出来:

代码语言:txt
复制
$ cd /home/ubuntu/github.com/TarsCloud/TarsFramework/build
$ make tarsstat-tar
$ make tarsnotify-tar
$ make tarsproperty-tar
$ make tarslog-tar
$ make tarsquerystat-tar
$ make tarsqueryproperty-tar

这样会在 /home/ubuntu/github.com/TarsCloud/TarsFramework/build 目录下分别生成上述六个组件的 tgz 文件。

接下来我们以 tarsstat 为例说明部署方法:

创建服务

点击 web 主页的 “运维管理” 选项卡,进入服务界面:

各参数按照如下填写:

  • 应用:填 “tars
  • 服务名称:填 “tarsstat
  • 服务类型:在下拉菜单中选 “tars_cpp
  • 模板:在下拉菜单中选 “tars.tarsstat
  • 节点:选择本机的出口地址,像笔者的情况,就是 172.19.16.13
  • SET:现阶段不用填,这是 tars 的进阶功能
  • OBJ:填 “StatObj
  • OBJ 绑定地址端口:可以手动调整,也可以点 “获取端口” 按钮自动分配
  • 端口类型:TCP
  • 协议:TARS

其他默认即可。填好后,点 “确定” 即可部署。注意,此时的 “部署”,只是在 tars 内注册了一个服务(占了个坑),但这个服务还没有上线提供可用的功能。

发布服务

部署了服务后,需要刷新页面,这样就可以看到左边 tars 的服务列表多了一项:“tarsstat

现在,我们需要真正地发布这个服务了。

点击 “tarsstat” 选项卡,可以看到上面有六个功能选项。点击 “发布管理”,视图如下:

勾选节点,然后点击 “发布选中节点”,界面如下:

这个时候点 “发布版本” 的下拉菜单,是没有内容的。我们需要点 “上传发布包”,在新打开的窗口,选择上一步 “创建服务” 时打包的 tarsstat.tgz 文件上传即可。上传成功后,我们再在 “发布版本” 下拉菜单中选择刚刚上传的包,然后点 “发布”。稍等一会后,我们只要看到 tarsstat 的状态变成如下,就是发布成功了:

其他各个服务的特殊参数

除了不需要额外配置数据库之外,接下来的五个服务的配置发布流程基本一致。但也有以下一些不同,读者在发布剩余服务的时候请注意修改:

  • 各服务的名称不同,请相应地修改;
  • 各服务的服务类型均为 “tars_cpp”,但是模板不同——每一个服务均有其对应的专用模板,比如 tarsconfig 对应 tars.tarsconfig 模板;
  • tarsquerystattarsqueryproperty 的 “协议” 应选 “非TARS”,其他服务为 “TARS”;
  • 各服务对应的 Obj 名称如下:
    • tarsnotify: NotifyObj
    • tarsproperty: PropertyObj
    • tarslog: LogObj
    • tarsquerystat: NoTarsObj(非 TARS 协议)
    • tarsqueryproperty: NoTarsObj(非 TARS 协议)

此外,以下这一步是 tarsstat 特有的步骤:在发布服务之前,需要进入数据库进行以下操作,防止 tarsstat 启动失败:

代码语言:txt
复制
MariaDB [(none)]> use db_tars;
MariaDB [db_tars]> CREATE TABLE `t_server_notifys` (   `id` int(11) NOT NULL AUTO_INCREMENT,  `application` varchar(128) DEFAULT '',  `server_name` varchar(128) DEFAULT NULL, `container_name` varchar(128) DEFAULT '' , `node_name` varchar(128) NOT NULL DEFAULT '',  `set_name` varchar(16) DEFAULT NULL,  `set_area` varchar(16) DEFAULT NULL,  `set_group` varchar(16) DEFAULT NULL,  `server_id` varchar(100) DEFAULT NULL,  `thread_id` varchar(20) DEFAULT NULL,  `command` varchar(50) DEFAULT NULL,  `result` text,  `notifytime` datetime DEFAULT NULL,  PRIMARY KEY (`id`),  KEY `index_name` (`server_name`),  KEY `servernoticetime_i_1` (`notifytime`),  KEY `indx_1_server_id` (`server_id`),  KEY `query_index` (`application`,`server_name`,`node_name`,`set_name`,`set_area`,`set_group`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
MariaDB [db_tars]> exit;

2019-09-22 注:当前最新版本已经不需要了,执行前述 sql 文件即可

所有服务均发布完成并状态正确之后,Tars 基础框架就部署完成啦,恭喜你!

日志查询

如果部署 Tars 框架服务过程中遇到什么错误,可以查阅的 log 在以下路径:

  • /usr/local/app/tars/app_log/tars

关于自动部署

Tars 其实还提供了一套比较简易的快速部署脚本。那个脚本我没有尝试过,但据说也是有一些坑……这里我推荐 maq128 同学 的文章:tars小白安装必成手册,分别讲述了快速部署、手工部署、docker 部署的内容。另外,如果有问题,读者也可以加入 Tars 官方交流群,不保证所有问题都能够精准回答,但是群里不少大神还是给了我不少启发。群号参见 Tars 官方文档


下一步研究

按照官方的建议,Tars 的所有基础服务都需要至少进行灾备部署,但是部署方式如何实现,并没有明确的说明或者建议。这是笔者后续准备实验的。

参考资料


本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

原文发布于:https://cloud.tencent.com/developer/article/1372998

目前发现以下博客未按上述协议进行转载,已构成侵权:

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
    • Tars 简介
      • 安装任务
        • 本文解决的问题
        • 环境准备
          • 系统准备
            • 软件准备
              • MySQL 问题
              • 备份
          • 安装支持软件
            • MySQL
              • 安装路径准备
              • 编译安装
            • Node.js
              • Tars 基础框架
                • 准备 Tars 数据库
                  • TIPS-1
                  • TIPS-2
              • 部署 Tars 基础框架
                • Tars 框架核心服务
                  • Tars web 管理平台
                    • Tars 框架基础服务
                      • 检查核心服务状态
                      • 部署其他基础服务
                  • 关于自动部署
                  • 下一步研究
                  • 参考资料
                  相关产品与服务
                  云数据库 MySQL
                  腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档