背景

Tars 简介

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

系列文章

  • 腾讯 Tars 基础框架手动搭建——填掉官方 Guide 的坑
  • 腾讯 Tars-Go 服务 Hello World——从 HTTP 开始
  • 腾讯 Tars-Go 服务 Hello World——RPC 通信

安装任务

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++ 开发环境需要以下开发组件:

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

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

mysql-server node.js(包括 npm)
TarsCloud/TarsFramework TarsCloud/TarsWeb TarsClous/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 基础框架准备环境。

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

$ sudo mkdir -p /usr/local/mysql
$ sudo chown ubuntu:ubuntu /usr/local/mysql

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

$ 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 下,那么我们就创建两个软链接:

$ ln -s /usr/include/mariadb /usr/local/mysql/include
$ ln -s /usr/lib/x86_64-linux-gnu /usr/local/mysql/lib

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

$ mkdir /home/ubuntu/mysql-5.6            # /home/ubuntu 是笔者系统的家目录,读者请注意替换。以下同理。

编译安装

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

$ 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 版

配置、编译、安装:

$ 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 基础框架准备的目录下:

$ ln -s /home/ubuntu/mysql-5.6/libmysqlclient.a /usr/local/mysql/lib/

Node.js

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

$ 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 的基础框架代码:

$ mkdir -p /homes/ubuntu/github.com/TarsCloud/TarsFramework
$ cd /homes/ubuntu/github.com/TarsCloud/TarsFramework
$ git clone https://github.com/TarsCloud/TarsFramework.git ./

编译之:

$ cd build
$ chmod +x build.sh
$ ./build.sh prepare
$ ./build.sh all

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

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

$ sudo mkdir -p /usr/local/tars
$ sudo chown ubuntu:ubuntu /usr/local/tars
$ cd /homes/ubuntu/github.com/TarsCloud/TarsFramework/build
$ ./build.sh install

准备 Tars 数据库

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

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

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

$ mysql -u root -p

进入 mysql 命令行后:

MariaDB [(none)]> grant all privileges on *.* to tars@localhost identified by 'tars2015';
MariaDB [(none)]> flush privileges;
MariaDB [(none)]> exit;

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

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

$ cd /homes/ubuntu/github.com/TarsCloud/TarsFramework/sql/
$ sed -i "s/192.168.2.131/172.19.16.13/g" `grep 192.168.2.131 -rl ./*`
$ sed -i "s/db.tars.com/172.19.16.13/g" `grep db.tars.com -rl ./*`
$ sed -i "s/10.120.129.226/172.19.16.13/g" `grep 10.120.129.226 -rl ./*`
$ chmod +x exec-sql.sh
$ ./exec-sql.sh

其中,172.19.16.13 是笔者的 DB 的 IP 地址,读者实际部署时请注意修改。

这些命令也给我们一个启发:数据库地址允许采用域名。

TIPS-1

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

$ cd /homes/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.sqlmodified:   tarsconfig.sqlmodified:   tarslog.sqlmodified:   tarsnotify.sqlmodified:   tarspatch.sqlmodified:   tarsproperty.sqlmodified:   tarsqueryproperty.sqlmodified:   tarsquerystat.sqlmodified:   tarsstat.sql

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

TIPS-2

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


部署 Tars 基础框架

Tars 框架核心服务

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

$ cd /homes/ubuntu/github.com/TarsCloud/TarsFramework/build
$ make framework-tar

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

$ 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 /homes/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。对操作已经很熟悉了的读者可以手动修改这些配置。不过也可以简单点地进行以下修改:

$ cd /usr/local/app/tars
$ sed -i "s/192.168.2.131/172.19.16.13/g" `grep 192.168.2.131 -rl ./*`
$ sed -i "s/db.tars.com/172.19.16.13/g" `grep db.tars.com -rl ./*`
$ sed -i "s/registry.tars.com/172.19.16.13/g" `grep registry.tars.com -rl ./*`
$ sed -i "s/web.tars.com/172.19.16.13/g" `grep web.tars.com -rl ./*`

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

  1. 本机地址,不能写 127.0.0.1
  2. 前述数据库的地址;
  3. tarsregistry 的 部署地址,可以不是本机;
  4. web.tars.comrsync 服务和 web 管理平台的部署地址。

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

$ cd /usr/local/app/tars
$ grep dbpass -rl ./*

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

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

$ 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

然后我们可以在 croncab 中配置核心基础框架的监控项:

* * * * * /usr/local/app/tars/tarsnode/util/monitor.sh

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

Tars web 管理平台

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

$ mkdir -p /homes/ubuntu/github.com/TarsCloud/TarsWeb
$ cd /homes/ubuntu/github.com/TarsCloud/TarsWeb
$ git clone https://github.com/TarsCloud/TarsWeb.git ./
$ sed -i 's/db.tars.com/172.19.16.13/g' config/webConf.js
$ sed -i 's/registry.tars.com/172.19.16.13/g' config/tars.conf

其中 172.19.16.13 是笔者机器的 IP,读者请注意

Tars web 是用 node.js 编写的,不需要编译。管理平台默认监听在 3000 端口上,可在 config/webConf.js 中修改 port 参数的值。

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

$ cd /homes/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 文件的路径参见后文)。

部署其他基础服务

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

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

$ cd /homes/ubuntu/github.com/TarsCloud/TarsFramework/build
$ make tarsstat-tar
$ make tarsnotify-tar
$ make tarsproperty-tar
$ make tarslog-tar
$ make tarsquerystat-tar
$ make tarsqueryproperty-tar

这样会在 /homes/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 启动失败:

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;

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

日志查询

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

  • /usr/local/app/TarsWeb/log
  • /usr/local/app/tars/app_log/tars

关于自动部署

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


下一步研究

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

参考资料

  • pm2 日志加时间戳
  • mysql/mariadb centos7 修改root用户密码及配置参数
  • tars 部署过程-youz1976的专栏
  • 腾讯Tars环境搭建中遇到的坑
  • tars各个自带的服务都是做什么的,又是怎么保障他们的可靠性的?
  • 请问t_server_notifys建表语句?
  • TARS 用户体系模块+资源模块使用指引
  • tars小白安装必成手册

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

本文地址:https://segmentfault.com/a/1190000017482106。
原文发布于:https://cloud.tencent.com/developer/article/1372998,也是本人的博客。

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

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

    背景 Tars 简介 腾讯 Tars 是腾讯内部使用的 TAF(Tencent Application Framework)的对外开源版,去掉了许多冗杂多余的部分.该框架集开发.运维.微服务.RPC ...

  2. CLion之C++框架篇-安装工具,基础框架的搭建(一)

    CLion之C++框架篇-安装工具,基础框架的搭建(一) 背景 日常学习C++,也就是看看书.在vim里写写代码.在日常项目开发中,也是边看书(一是系统性理解.二是找找有什么更好的代码编写方式)边写代 ...

  3. 腾讯云服务器如何手动搭建LAMP环境?

    LAMP 环境是指 Linux 系统下,由 Apache + MariaDB + PHP 及其它相关辅助组件组成的网站服务器架构.本文本文档介绍如何在腾讯云云服务器(CVM)上手动搭建 LAMP 环境 ...

  4. 腾讯微服务框架 Tars 的 Go 性能提升之路

    前言 在 4 月 27 日举办的 Gopher China 2019 中,来自腾讯 Tars 团队的核心成员陈明杰进行了一场题为<Tars Go 性能提升之路>的演讲.陈明杰,负责腾讯容器 ...

  5. 腾讯微服务框架Tars的初体验

    最近研究了一下腾讯的微服务体系开发框架. 搭建过程:https://github.com/TarsCloud/Tars/blob/master/Install.zh.md 写一个HelloWorld: ...

  6. 腾讯云服务器CVM(CentOS 7、Tencent Linux)手动搭建LNMP环境(linux+Nginx+Mariadb+PHP)

    手动搭建云服务器运行环境就是喜欢折腾,如果觉得麻烦的网友可以使用LNMP镜像直接启动CVM实例,以便快速建站. 腾讯云服务器CVM(CentOS 7.Tencent Linux)手动搭建LNMP环境( ...

  7. 腾讯Tars框架剖析(一)---Tars框架原理及架构

    文章目录 Tars是什么? Tars能干什么? Tars包含了什么? Tars的设计思想是什么? Tars的架构是怎样的? 底层的协议层 上层的服务层 介绍 组成 服务节点: 公共框架结点 Mysql ...

  8. Koa入门(一)—— Koa项目基础框架搭建

    Koa项目基础框架搭建 项目初始化 项目自动重启 配置ES6语法 基本目录搭建 配置env信息 自动加载路由 统一异常处理 自定义异常 异常处理中间件 中间件配置 目录别名配置 项目初始化 mkdir ...

  9. 原生微信小程序项目基础框架搭建

    原生微信小程序项目基础框架搭建 文件目录结构 1. 环境变量(开发环境, 线上环境,测试环境)便于在不同环境的切换 接口的url webview的前缀url 埋点相关的环境参数 本地存储的环境变量配置 ...

最新文章

  1. LeetCode简单题之比赛中的配对次数
  2. 阿里飞猪个性化搜索排序探索实践
  3. 数据查询和业务流分开_数据仓库介绍与实时数仓案例--阿里
  4. 如何在 ASP.NET CORE 中获取客户端 IP ?
  5. 软件工程实践小队Scrum Meeting
  6. 卫生纸玫瑰花折法5步_手工教程:做一个漂亮的玫瑰花捧花,用折纸表达我喜欢你...
  7. android studio jdy08,JDY-08模块 蓝牙4.0 BLE CC2541 airsync iBeacon 兼容arduino
  8. WEB安全扫描器Netsparker推荐给大家
  9. 数控计算机辅助编程软件,Cimatron数控编程软件
  10. docker-compose listing workers for Build: failed to list workers
  11. Can't open /dev/sdb1 exclusively. Mounted files
  12. 傅佩荣谈道家逍遥自在的人生
  13. 百度大脑人脸情绪实时识别攻略
  14. findIndex()
  15. 【数据可视化】数据可视化之美——用专家的眼光洞察数据
  16. 【计算机网络】物理层 : 相关参数 ( 码元 | 码元进制 | 速率 | 码元传输速率 | 波特 | 信息传输速率 | 带宽 | 码元速率计算示例 )★
  17. 第六章 利用数组处理批量数据
  18. VAPS XT开发入门教程02:安装配置
  19. java毕业设计超市会员积分管理系统Mybatis+系统+数据库+调试部署
  20. 一张表中存商品分类,商品下面还有分类的建表方法

热门文章

  1. 聚观早报 | 小冰启动GPT克隆人计划;ofo创始人在美创业改做咖啡
  2. RSA--e与φ(n)不互素时
  3. 乙烯基硅油,液体硅胶中的“神奇助手”
  4. 前端、后端、全栈到底指的是什么?
  5. 我们征服托业,还是被托业征服?
  6. 达梦(DM)数据库认证管理员培训记录
  7. PyCharm 格式化代码 (Reformat Code)
  8. css实现圆形渐变色边框
  9. 【Unity3D】【NGUI】UIProgressBar
  10. web前端教程分享:常见 React 面试题