Akawa

ETY001的博客

部署YOYOW见证人有几个月了,发现貌似没有人关注丢块的问题,我也没有找到有相关的开源软件可以去完成丢块自动下线的功能。像 Steem 社区有太多的类似程序了,python 的、nodejs 的,多的数不胜数。只能说 YOYOW 还是很年轻。

作为一个 YOYOW 的见证人,有义务去开发一款这样开源版本的工具。经过一晚上的折腾,基本功能已经是完成了。代码库在 这里。这个工具是基于docker进行部署的,如果你看了上一篇我写的《YOYOW 见证人教程》 , 那么这个工具的部署应该会很轻松。因为我花了大量的时间在部署脚本上(大约6个小时),目的就是尽可能把部署过程傻瓜化。

准备

  • 一台 Linux 服务器,装有 docker , wget
  • 如果需要通知服务,请自行注册discord,并创建一个新的服务器、频道和频道的webhook(文章最后有个简易获取 Webhook 的教程)。

开始

1.首先下载代码

1
2
git clone https://github.com/ety001/yoyow-witness-watcher.git
cd yoyow-witness-watcher

2.部署 yoyow_client,并提供 RPC 服务。

1
./init.sh

首先提示你输入 yoyow_client 的下载地址:

1
2
3
4
5
6
7
8
*********************************************
Welcome to use YOYOW witness watcher.
This tool is made by ETY001. (https://github.com/ety001)
My YOYOW ID is 485699321. It's pleasure to get your votes!
*********************************************

Please input current yoyow_client download URL (https://github.com/yoyow-org/yoyow-core/releases/latest):
https://github.com/yoyow-org/yoyow-core/releases/download/v0.2.1-180313/yoyow-client-v0.2.1-ubuntu-20180313.tgz

下载地址可以在 https://github.com/yoyow-org/yoyow-core/releases/latest 找到,填写下载地址后,回车继续。

当看到出现 Listening for incoming HTTP RPC requests on 0.0.0.0:9999 以及 new >>> 的时候说明 yoyow_client 的 docker 镜像已经做好,现在开始创建钱包并导入你的账号

1
2
3
4
5
6
7
8
9
10
11
Create wallet
Logging RPC to file: logs/rpc/rpc.log
3505859ms th_a main.cpp:120 main ] key_to_wif( committee_private_key ): 5KCBDTcyDqzsqehcb52tW5nU6pXife6V2rX9Yf7c3saYSzbDZ5W
3505862ms th_a main.cpp:124 main ] nathan_pub_key: YYW6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
3505862ms th_a main.cpp:125 main ] key_to_wif( nathan_private_key ): 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
Starting a new wallet with chain ID ae4f234c75199f67e526c9478cf499dd6e94c2b66830ee5c58d0868a3179baf6 (from egenesis)
3505863ms th_a main.cpp:172 main ] wdata.ws_server: wss://wallet.yoyow.org/ws
3506840ms th_a main.cpp:177 main ] wdata.ws_user: wdata.ws_password:
Please use the set_password method to initialize a new wallet before continuing
3509652ms th_a main.cpp:243 main ] Listening for incoming HTTP RPC requests on 0.0.0.0:9999
new >>>

先设置本地钱包密码(比如 123456)

1
set_password 123456

解锁本地钱包

1
unlock 123456

导入你的 YOYOW 账号

1
import_key YOUR_YOYOW_ID  YOUR_YOYOW_ACTIVE_KEY

完成以上工作后,按 ctrl + d 退出钱包,docker 容器开始重启

直到看到 Finish 且已经在监听 9999 端口时,整个 yoyow_client 的部署完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Get Status
00200e8bde55 yoyow_client "/bin/sh -c '/data/y…" 10 seconds ago Up 10 seconds yoyow_client

Logs
Logging RPC to file: logs/rpc/rpc.log
140909ms th_a main.cpp:120 main ] key_to_wif( committee_private_key ): 5K**********************5W
140910ms th_a main.cpp:124 main ] nathan_pub_key: YY************************CV
140910ms th_a main.cpp:125 main ] key_to_wif( nathan_private_key ): 5****************************3
140912ms th_a main.cpp:172 main ] wdata.ws_server: wss://wallet.yoyow.org/ws
141820ms th_a main.cpp:177 main ] wdata.ws_user: wdata.ws_password:
145239ms th_a main.cpp:243 main ] Listening for incoming HTTP RPC requests on 0.0.0.0:9999

************
Finish!

3.部署监控程序

直接运行下面的命令开始部署

1
./install_bot.sh

提示输入你的 YOYOW ID

1
2
3
# ./install_bot.sh
Please input YOYOW ID:
485699321

提示输入你签名块用的公钥。

1
2
3
4
Please input Your Public Key:
If you have multiple public keys, separate them with commas
eg. YYW7TSRLZ9EXZps37Kt31qa7qi,YYW7TSRLZ9EXZpZqk25atoL2s37
YYW7TSRLZ9EXZpZqk25atoL2s37Kt31qa7qi78ZR368kCN969rFiT,YYW733FxEEaAFTHxdTJdowZyQzJ3JnPocsVmdq4aSsm1gSd1VkYDC

> 如果你有多台备机,可以用逗号把多个公钥隔开填写,请务必把当前正在运行的节点的公钥放在第一位,程序会在检测到丢块后,自动依次往后切换,直到所有节点都不可用。因此,如果你有两个节点的话,当第一个节点挂掉,程序自动切换到第二个备份节点后,赶紧去修第一个节点,第一个节点重启可用后,一定要重新部署下bot程序,并且填写公钥时,把目前的第二个节点的公钥放在前面

提示输入你的本地钱包密码

1
2
Please input wallet password:
123456

提示输入 discord 的 webhook 地址,如果你想获取通知的话,就配置这项,否则留空。最后会简单说下怎么获取 webhook 地址

1
2
Please input Discord webhook for notify (If you don't need it, leave empty.):
https://discordapp.com/api/webhooks/433204170/X2RWo7-qiFlnMtQeQkk_sSgb5Vn0rQVWZCF5f

当你看到类似以下信息的时候,就已经完成了所有部署工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Get status
string(20) "global value in init"
array(2) {
[0]=>
string(53) "YYW7TSRLZ9EXZpZqk25atoL2s37Kt31qa7qi78ZR368kCN969rFiT"
[1]=>
string(53) "YYW733FxEEaAFTHxdTJdowZyQzJ3JnPocsVmdq4aSsm1gSd1VkYDC"
}
string(9) "485699321"
string(27) "http://172.20.99.2:9999/rpc"
int(3)
send_notify:""
witness_info: [{"id":"1.5.118","account":485699321,"name":"yoyo485699321","sequence":1,"is_valid":true,"signing_key":"YYW7TSRLZ9EXZpZqk25atoL2s37Kt31qa7qi78ZR368kCN969rFiT","pledge":"4800000000","pledge_last_update":"2018-04-09T16:27:36","average_pledge":"4769814330","average_pledge_last_update":"2018-04-10T09:29:36","average_pledge_next_update_block":6208938,"total_votes":"1012502907669","by_pledge_position":"0","by_pledge_position_last_update":"13192707760156474609520154309632187","by_pledge_scheduled_time":"13192779100955781906176323330356157","by_vote_position":"0","by_vote_position_last_update":"8327365446400524735205121087916251","by_vote_scheduled_time":"8327365782480909634055199728870765","last_confirmed_block_num":6208607,"last_aslot":6220862,"total_produced":1143,"total_missed":3,"url":"https:\/\/github.com\/ety001"}]
total_produced: 1143, total_missed: 3
2018-04-10 10:23:38


***********
Finish!!

如果想查看监控程序的工作状态,执行下面的命令即可

1
docker logs --tail 50 yoyow_witness_watcher

4.卸载

卸载非常的简单,只需要执行下面的命令即可

1
./uninstall_bot.sh && ./uninstall.sh

> 如果你只想重新部署监控程序,只需要执行 ./uninstall_bot.sh 即可,执行完后重新执行 ./install_bot.sh。如果你中途执行安装脚本有错误的话,也需要先执行卸载脚本后,再重新执行安装脚本。卸载脚本如果都要执行的话,执行顺序一定要是先 uninstall_botuninstall

申请 Discord 的频道 Webhook

注册账号就不说了,打开桌面app界面(网页界面应该也差不多),在左下角找到一个加号,点击后如下图

y1.png

选择创建一个服务器,进入下个界面,配置下你的服务器的名字和位置后,即可完成创建,进入你的服务器,新建一个频道,然后在频道右侧有个齿轮,点击一下,如图

y2.png

打开频道配置页面后,找到 Webhook 选项,然后创建一个新的 Webhook,如图

y3.png

填写下 Webhook 的名字后,即可完成创建,里面的 URL 即为你的 Webhook 地址。

欢迎给我投票,我的 YOYOW 号是 485699321

前言

YOYOW 是一个基于区块链的内容激励网络,YOYOW 虽然给人第一印象是模仿 Steem,其实不然。YOYOW 在做的事情应该是一个区块链版的 UCenter。其他的事情也不多说了,不是教程范畴的,请自行去 官网 阅读 白皮书

前置技能 和 准备工作

  • 基础的 Linux 知识
  • 基础的 Docker 知识
  • 有一台运行有 Docker 的服务器(目前 2G 内存,50G 硬盘就足够足够了)
  • YOYOW 账号,且至少账号内有 11000 个币(抵押需要1w,手续费需要1k)

开始我们的表演

1.创建以下目录

1
2
# mkdir -p /yoyow/data
# mkdir -p /yoyow/yoyow_node_data_dir

2.下载 YOYOW 的最新版程序,https://github.com/yoyow-org/yoyow-core/releases
请分别下载 yoyow-client-v0.2.1-ubuntu-20180313.tgzyoyow-node-v0.2.1-ubuntu-20180313.tgz,并解压 yoyow-clientyoyow-node/yoyow/data 目录。(可能你看到此文的时候,版本号已经变了,但是下载 Ubuntu 环境下的 yoyow-clientyoyow-node 肯定是没错的)
请直接 watch 这个项目,以免错过版本更新造成丢块。

3.下载 Dockerfile 文件到任意目录

1
# curl https://gist.githubusercontent.com/ety001/640f944f7299cae4af4e3ef092a5f4a8/raw/192d36950d580996c176e23f5d5c4ae6da26110e/yoyow_Dockerfile -o Dockerfile

4.打开 Dockerfile 文件,注释掉最后一行,如下

1
2
3
4
FROM ubuntu:16.04
Volume /data
Volume /yoyow_node_data_dir
# CMD /data/yoyow_node --rpc-endpoint -w 485699321 --private-key '["YYW7TSRLZ9EXZpxxxx","5JbDUxxxxxxxxxx"]'

保存退出。

5.生成一个镜像

1
# docker build -t yoyow .

6.启动一个容器来运行 yoyow-node

1
# docker run --name yoyow -d -v /yoyow/data:/data -v /yoyow/yoyow_node_data_dir:/yoyow_node_data_dir yoyow /data/yoyow_node --rpc-endpoint

7.等待数据同步到最新,可以通过下面的命令来查看容器的运行情况

1
# docker logs --tail 10 yoyow

上面的命令是显示最后10行的,如果想显示更多行,请自行修改,去掉 --tail 参数可以显示全部输出信息。

8.同步完数据后,执行下面的命令可以打开本地钱包

1
# docker exec -it yoyow /data/yoyow_client -w /data/wallet.json -s ws://localhost:8090

第一次打开本地钱包,会要求你设置一个本地钱包的密码,如下图(请设置后牢记)

输入 set_password 命令完成密码设置,本教程内设置的密码是 123456 如下

1
2
3
4
5
Please use the set_password method to initialize a new wallet before continuing
new >>> set_password 123456
set_password 123456
null
locked >>>

9.解锁钱包

1
2
3
4
locked >>>  unlock 123456
unlock 123456
null
unlocked >>>

10.导入资金密钥 Active keyActive key 去这里可以找到 https://wallet.yoyow.org/#/settings/viewpurview ),导入命令如下

1
unlocked >>>  import_key   你的数字账号   你的ActiveKey

11.生成一对新的公私钥对,用于签名打包的块。**请备份好,如果丢失,需要重新生成新的公私钥对,并重新配置 yoyow_node**。

1
2
3
4
5
6
7
unlocked >>>  suggest_brain_key
suggest_brain_key
{
"brain_priv_key": "JIGGETY DEATHLY MUSTEE WINDORE CHAGUL WACE TUQUE BEMOON FLAVIC PITCHY SEVENER FELINE VIDETTE RUMNEY OVUM XENYL",
"wif_priv_key": "5KMJDKiUcWr9J2pPu9YdAQnbAiMKKxx2DA4W5ALfvgkUsWyXNWX",
"pub_key": "YYW87JoiJguwTWgSXZBHHaA78xiaNaEh5Lup1rNJGEg37Z4huNGyS"
}

12.创建见证人

1
unlocked >>>  create_witness   你的数字账号名    见证人签名公钥    押金金额(10000+)    YOYO   你的宣传链接   true

如果创建成功,在 https://yoyow.bts.ai/witness?locale=zh-CN 就可以查到了。

退出本地钱包的方法:ctrl + d

13.停止刚才创建的容器并删除容器和镜像

1
2
3
# docker stop yoyow
# docker rm yoyow
# docker rmi yoyow

14.打开刚才的 Dockerfile,把刚才注释掉的最后一行取消注释,并且 485699321 修改为你的数字账号,YYW7TSRLZ9EXZpxxxx5JbDUxxxxxxxxxx 分别修改为刚才生成的公私钥,即 YYW87JoiJguwTWgSXZBHHaA78xiaNaEh5Lup1rNJGEg37Z4huNGyS5KMJDKiUcWr9J2pPu9YdAQnbAiMKKxx2DA4W5ALfvgkUsWyXNWX,修改完后,保存退出。

15.重新生成镜像

1
# docker build -t yoyow .

16.重新启动容器

1
docker run --name yoyow -d --restart always -v /yoyow/data:/data -v /yoyow/yoyow_node_data_dir:/yoyow_node_data_dir yoyow

到这里,就完成了见证人服务器的搭建工作。

一些常用的命令

1.打开本地钱包(其中 wallet.json 即为你本地钱包文件,在母机的 /yoyow/data 目录下,注意保护)

1
# docker exec -it yoyow /data/yoyow_client -w /data/wallet.json -s ws://localhost:8090

2.如果你要维护节点,为了避免错过块,请先下线见证人,然后再进行维护。启停见证人使用 update_witness 命令,其格式如下:

1
2
3
4
5
6
7
8
unlocked >>>  update_witness    您的数字账号名     签名用的公钥    押金金额(10000)   YOYO    链接     true
# 不需要修改的内容填null,不能填写和修改前一样的参数,否则会报错)

# 下线见证人
unlocked >>> update_witness 485699321 YYW1111111111111111111111111111111114T1Anm null null null true

# 上线见证人
unlocked >>> update_witness 485699321 YYW87JoiJguwTWgSXZBHHaA78xiaNaEh5Lup1rNJGEg37Z4huNGyS null null null true

3.查看可以领取的见证人工资

1
unlocked >>>  get_full_account 485699321

其中 uncollected_witness_pay 的数值除以10万就是你未领取的见证人工资。

4.领取见证人工资

1
unlocked >>>  collect_witness_pay 485699321 money YOYO true

485699321 换成你的账号,money 换成你要申领的工资数。

节点升级工作

如果遇到程序升级,那么需要首先下载最新版的 yoyow_nodeyoyow_client,下线见证人后停止容器

1
# docker stop yoyow

用新版的程序覆盖之前的程序后,再启动容器,

1
# docker start yoyow

容器启动数据同步完后,再上线见证人。

完结

以上即为 Docker 版的部署教程,如有遗漏请留言,欢迎给我投上一票,我的账号是:485699321

一切的一切都要从一封垃圾邮件开始。

当时还是2013年11月的某天,在我邮箱里发现了一封收XRP的邮件,于是在 V2EX 上 发了个帖子,想看看社区有知道 XRP 是啥的人没有。后来就从接触 XRP 开始,又知道了 BTC,就这样算是关注到了币圈。那个年代真的是除了 BTC 、Ripple、LTC外都是山寨币。

当时有看到过 PTS,但是并没有了解这是个啥,因为自己脑子里一直认为其他的都是山寨币。后来也听说了 Stellar,知道 Stellar 是从 Ripple 继承过去的,所以也并不重视这个。

后来是因为去年(你没看错就是去年)在比特时代上看到了比特股的简介,瞬间来了兴趣,就开始买入了一点,然后研究起来。

所以,我对于这两者的历史了解并不多,我只把我知道的说出来,有不对的地方,还请各位指点。

先说 Stellar。由于 Stellar 继承于 Ripple, 所以我认为 Stellar 也同样是中心化的,具体 Stellar 的中心是公司还是个人,我其实也不清楚。 Ripple 和 Stellar 其实只是借助于区块链来完成分布式账本,让交易数据不可逆。之所以采取中心化,我的理解是为了解决 BTC 的转账慢和手续费高的问题。BTC 转账慢和手续费高的问题由来已久,并不是这两年才有的,在我 2013年刚接触的时候,就有人提出 BTC 的转账慢是无法完成类似于支付宝这样的交易的。于是很多人都在探索这一块,其中 Ripple 就是其中之一。同时 Ripple 的目的也是为了解决跨国结算和支付的问题。既然 Stellar 是继承于 Ripple,所以 Ripple 有的特性,Stellar 也都一样存在着。

Stellar 网络中可信节点数量应该是确认的,这个 P2P 网络中,部署着 API 节点、Federation Server、Bridge Server。这其中 API 节点的作用是为用户的钱包以及其他的应用提供数据服务;Federation Server我的理解就是提供一个 Stellar 网络中的 DNS服务,比如一些 Anchor 的地址可以用类似邮件地址的格式来代替,这个工作就是由可信的 Federation Server来完成解析的;关于Bridge Server 我没有接触过,所以跳过。

除了以上三个类型的服务外,还有就是 Anchor 了。Stellar 网络的通用代币是 XLM(有些交易所也称作 STR ) ,就像 Bitcoin 网络里的通用代币是 BTC 一样。而为了实现其他的货币,就要靠 Anchor 来实现。Anchor 是 Stellar 网络中最关键的一环,我一般称这个为网关,因为网关可以发行和销毁代币,这就提供了资金进入的途径。

比如说,我做了一个人民币的网关,那么我可以在我的网关上发行一个代币叫做 CNY,然后别人只要在钱包里设置信任我这个网关,就可以直接在钱包的交易页面,从我的网关上进行挂单,进行 XLM / CNY 交易。如果两个人同时信任了我这个网关,那么这两个人也可以通过 Stellar 的网络进行 CNY 转账。注意这里转账的 CNY 是由我这个网关发行的。也就是说现在如果有另外一个网关也发行 CNY,那么这两个 CNY 是不通用的。(不过这里要提一点,就是在 Ripple 的网络中,有一种方法是可以置换的,比如甲在A网关有50CNY,没有信任B网关,他想转50CNY给乙,而乙没有信任A网关,只信任了B网关,此时如果丙同时信任了A和B网关,并打开了置换功能,且丙在B网关有至少50CNY,那么系统会在网络里找到这条通道完成转账,即甲把A网关的50CNY给了丙,丙把B网关的50给了乙。当年我就是这么被骗子置换了将近1w个 Ripple 币。)

总结一下,其实 Stellar 只是借助了区块链来完成数据不可逆的工作,而其中的网关有些像交易所的角色,完成资金的进出。对于普通用户来说,通过 Stellar 网络进行交易和转账也很便捷,具体出块时间忘记了,但是很快。

下面再简单描述下我理解中的 Bitshares。比特股在一开始打造的时候,就是按照去中心化的交易所的思路建设的,而其中重要的核心就是 DPOS 机制来保证相对的去中心化。BTS 的网络分为三种类型的节点,P2P节点、见证人节点、API节点。相对于 Stellar 来说差不太多。只是 BTS 引入外部资金的方式很不一样,通过抵押其网络中的核心代币 BTS 来获取其他法币代币,然后再由通过抵押 BTS 获得法币代币的人来做承兑商,完成资金的进出场。我觉得这样的做法无异于是增加了整个系统的运行风险,因为我认为这会让盘子里所有的货币都跟 BTS 的价值挂钩了。我个人觉得这个不应该是由抵押来实现法币代币价值锚定,而应该通过信用来实现价值锚定。也就是说,BTS 在抵押这个操作上把方向搞反了,想要试图用 BTS 的价值来决定现实中法币的价值。这个问题也是我在过去几个月内盘经历的一次次爆仓中体悟到的。

但是总的来说,Bitshares 吸引我的地方还是在 DPOS 这样的机制。并且我觉得 BTS 应该是目前为数不多的,创始人团队离开后,通过社区还能维持运营的币种。随着对币圈的深入,我现在很相信相对的去中心化才是未来。一味追求去中心化,其实是盲目的。并不是所有的场景都需要去中心化。总结一下 BTS 就是哲学很牛逼,但是产品还需要再打磨,但是市场到底留给 BTS 还有多少时间允许他打磨产品,是个问号。

以上是我的浅薄分析,如有错误,请指出。

最近完工的 StellarBot v0.0.8 对核心进行了重写,由于之前赶比赛进度,一直没有在offer这块搞明白。这次花了大量的时间来研究orderbook和创建offer这两部分的重要参数。这篇文章就是对于之前研究的一个总结。(是不是现在就已经开始晕了?一会order一会offer的。)

本文将会根据 base/counter 为交易单位来总结,如果对于 base/counter 还不明白的,请先看我之前写的 这篇文章,里面解释了这种单位的意思是怎样的。

Orderbook

1
GET /order_book?selling_asset_type={selling_asset_type}&selling_asset_code={selling_asset_code}&selling_asset_issuer={selling_asset_issuer}&buying_asset_type={buying_asset_type}&buying_asset_code={buying_asset_code}&buying_asset_issuer={buying_asset_issuer}&limit={limit}

上面的就是 OrderbookREST API。我们可以看到这个接口有以下参数:

name notes description example
selling_asset_type required, string Type of the Asset being sold native
selling_asset_code optional, string Code of the Asset being sold USD
selling_asset_issuer optional, string Account ID of the issuer of the Asset being sold GA2HGBJIJKI6O4XEM7CZWY5PS6GKSXL6D34ERAJYQSPYA6X6AI7HYW36
buying_asset_type required, string Type of the Asset being bought credit_alphanum4
buying_asset_code optional, string Code of the Asset being bought BTC
buying_asset_issuer optional, string Account ID of the issuer of the Asset being bought GD6VWBXI6NY3AOOR55RLVQ4MNIDSXE5JSAVXUTF35FRRI72LYPI3WL6Z
limit optional, string Limit the number of items returned 20

(该表格来自 https://www.stellar.org/developers/horizon/reference/endpoints/orderbook-details.html

官方给的这张表格,感觉太不好理解了,以下是我总结出来的参数和 base/counter 的对应关系:

1.png

再结合着实际的数据来看一下(接口 返回数据与钱包数据的对应图):

注意 Orderbook 接口返回的数据里,买卖单的 amount 是不同货币的》

提交 Offer 的各种参数

Stellar 系统里把单个订单称作 offer,这就跟之前的 orderbook 感觉跟别扭。这样的命名别扭会一直贯穿整个开发过程,所以我直接在我的代码里用了 order 代替 offer

管理订单的接口文档 在这里 可以看到,我摘录过来相关的参数表格如下:

Field Type Description
offer_id number Offer ID.
amount string Amount of asset to be sold.
buying_asset_code string The code of asset to buy.
buying_asset_issuer string The issuer of asset to buy.
buying_asset_type string Type of asset to buy (native / alphanum4 / alphanum12)
price string Price to buy a buying_asset
price_r Object n: price numerator, d: price denominator
selling_asset_code string The code of asset to sell.
selling_asset_issuer string The issuer of asset to sell.
selling_asset_type string Type of asset to sell (native / alphanum4 / alphanum12)

这里面最需要注意的就是 price 的计算是不同于 orderbook 中的 price 的。,以下是我总结的参数(params)和 base/counter 的对应关系:

创意 - 9.png

总结

开发中,主要注意的就是各个位置的 priceamount 计算和其代表的意义。多对照钱包和接口返回数据看几遍,应该就可以慢慢的参透其中的奥义,也就能看明白我总结的两张图里面的意思。再开发的时候,我的这两张图就会起到类似公式一样的作用。

这篇可能又会是一篇比较晦涩的文章了。可能也许写完了也就只有我自己能看懂了吧。。

在没有开发恒星做市机器人之前,一直都没有仔细关注过交易市场的价格单位。

由于交易市场之前都是 CNY 和具体的数字货币交易,所以交易所显示的价格都是买一个数字货币需要多少 CNY,我只需要看具体的数值即可,并不影响我判断什么时候买入,什么时候卖出。

在开发第一版的机器人的时候,由于只是在单网关下做 XLMCNY这一个交易对,也就没有在意价格单位的问题。

但是从开发第二版机器人开始,由于加入了多网关多币种之间互相做市的功能,就不得不看看具体的单位到底代表什么意思了。

之前每次扫到类似 BTC/CNY 这样的单位的时候,总以为这是个分数,比如 60000 BTC/CNY 我会以为是每一个 CNY 可以买到 60000 个 BTC,由于这个例子使用的是 CNY ,我们心里清楚目前 BTC 值多少 CNY,因此才知道我刚才的阅读单位的方式是错误的。

目前我开发机器人过程中,会出现两个陌生币种之间的交易,这个时候,如果不能真正了解价格单位的意义,开发出来的机器人肯定会是有问题的。

所以到底类似 BTC/CNY 这样的交易对价格单位该如何正确解读呢?

在说正确方法之前,还要再插一句,就是 BTS 内盘的价格单位其实在很长一段时间都是给我有误导作用的。我们看一下在内盘抵押 BTS 的时候,出现的喂价和强平触发价的单位。

这里的单位就真的是分数式的解读啊!比如强平触发价 2.97143 BTS/bitCNY,就是当 1 个 bitCNY 可以买到 2.97143 个 BTS,也就是 1 个 BTS 值大约 0.3365 bitCNY 的时候爆仓。

下面就来说下到底该如何解读交易所的交易对的价格单位。

我以 base currency and counter currency 作为关键词,在 Google 上搜索了下,发现了这个解释 https://www.investopedia.com/terms/b/basecurrency.asp

简单来说,这是外汇市场的一个约定俗成的表示方法,而 不是 一个分数形式的表示,只是通过先后顺序来表示关注程度。一个交易对的价格使用类似 base currency/counter currency 的格式来表示,意味着我更关注 base currency 的价值是升了还是跌了,也就是我买一个 base currency 要花多少 counter currency 或者 卖一个 base currency 能得到多少 counter currency。就是这么简单的按照顺序阅读即可。

举个例子,比如说 BTC/CNY 这个交易对,之前 60000 BTC/CNY 应该解读为我购买 1 个 BTC 需要花费 60000 个 CNY,如果购买一天后价格变为了 70000 BTC/CNY,就意味着我关注的这个 base currencyBTC 升值了。

总结一下,其实 counter currency 就是你手里的筹码。base currency 是你想持有的。

这样一来,你关心哪个币的涨跌,就把哪个币设置为 base currency 就可以轻松的了解是否升值了。

以上就是完整的价格单位如何解读的内容了,下面是吐槽内容,选读:

除了恶心的价格单位外,再说一下 bidask,这个也是让我头疼的东西。
放狗搜索了下,发现了这篇文章,https://www.bitcoinmarketjournal.com/difference-bid-ask-buy-offer-cryptocurrency-trading/,发现老外也真是够了。
原来 bid price 代表了最高的买价,ask price 代表了最低的卖价,而 buy pricesell price 只是代表最终的成交价。。。
WTF,为啥要多搞出来两个名词,对于中文来说都是买价卖家,无非加上最低和最高这样的形容词罢了。。。
我还要吐槽的是,恒星币的接口返回的 orderbook 里用 buysell 来表示买单列表和卖单列表并没有不严谨吧,反而用的是 asksbids 来表示卖单列表和买单列表。每次我都是要反应半天!只能说还是我的英语学的不好。
说到 orderbook,又想起了另外一个槽点,就是在恒星币的 API 体系里清一色的都是 offer,而这里却是 orderbook,你咋不叫 offerbook 呢?
吐槽完毕!

有朋友推荐了一个设备,我还没有测试,不过原理应该跟自己用树莓派搭建的系统一样,购买地址:https://item.taobao.com/item.htm?spm=a230r.1.14.53.250350a1rJhohU&id=558848686579&ns=1&abbucket=18 – 更新于 20180208

对于出国狗来说,在国外想要使用国内手机语音短信服务是个比较头疼的事情。这篇教程将教你用树莓派基于
Asterisk 实现一个 PBX 系统。最终的效果是:你可以在国外通过互联网使用你国内的手机号,享受的是国内手机号的资费。

基本的原理图

1.png

需要准备的东西

  • 树莓派3B(使用2代也可以,不过性能不是很好)

2.jpg

  • 一个带语音支持的 3G 卡托(尽量买华为的,并且一定要注意带语音支持,一般带语音的都是要卖出海外的,卖给国内的都是阉割掉语音功能的。我手里还有4个,有需要的可以找我,亲测可用,150国内包邮,国外的可以考虑从 阿里巴巴 上搜索 3g dongle voice 来购买。按照我两年前的实验来看,50多 CNY 的带语音卡托在树莓派上识别不出来,建议优先考虑华为,另外在 这里 有一份测试通过的型号清单,不过某些型号貌似也有好几种版本,比如我曾经买到过一个E169是没法用的。)

3.jpg

  • 一个带电源的USB HUB(一定要带电源,因为供电不足的话,来去电的时候可能不稳定)
  • 一根HDMI转VGA线(如果有HDMI显示器,可以忽略该配件)
  • 一张至少8G的TF卡(建议买树莓派的时候一并购买)
  • 5V2A的电源

前置技能

  • Linux基本知识
  • 最好有折腾过树莓派
  • 折腾的精神

基础配置

1.首先我们需要去 http://www.raspberry-asterisk.org/downloads/ 这里下载最新的镜像,该镜像是基于 Debian
已经封装好的 FreePBX 系统,本次教程使用的是 raspbx-03-12-2017.zip,其中 Asterisk 13.18.3, FreePBX 14.0.1.20
备注:该网站需要翻墙访问!

2.下载后,解压 raspbx-03-12-2017.zip,使用你熟悉的烧录软件,把解压出来的 .img 文件烧录进TF卡中。推荐使用 Etcher 进行烧录操作。用 Etcher 烧录还是比较方便,只需要三步即可。第一步选择镜像文件,第二步选择你的TF卡,第三步点击 Flash 即可开始。

3.插入TF卡到树莓派中,然后上电。系统默认用户密码为: root / raspberry

4.登陆后,先配置 WiFi (如果计划使用网线,可以跳过该步,建议使用网线,稳定),打开 /etc/wpa_supplicant/wpa_supplicant.conf 文件,

1
2
3
4
5
6
7
8
country=GB
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
# 增加如下配置,WiFi的ssid和密码
network={
ssid="ety001_router"
psk="12345678"
}

增加配置后,输入 reboot 进行重启,重启后,ifconfig 就能看到 IP 了,系统的 ssh 默认是开启状态,现在就可以使用 ssh 了。

另外镜像默认使用 4G 空间,如果你想扩展到 TF 卡全部空间,执行下面的命令

1
raspi-config

选择 Advanced Options ,再选择 Expand Filesystem,即可完成扩充。除此之外,也可以用 fdisk 命令完成,具体方法可以参考我博客上很早之前的一篇 博文

5.打开浏览器,访问你树莓派IP,会看到如下的配置页面

6.增加管理用户后,显示下面的登录界面,

7.点击 FreePBX Administration 进行管理员登陆,开始配置,登陆后进行语言和时区设置

8.设置成功后,进入了管理主界面

9.从 Application => Extensions => Add Extension => Add New PJSIP Extension

10.需要填写的项目有 User ExtensionDisplayNameSecretLink to a Default User.

7.png

其中 User Extension 是你的内线号码,用于呼叫和登陆客户端;
DisplayName 是用于呼叫时的显示,可选填;
Secret 是你在客户端登陆时需要填写的密码,请使用健壮的密码,详见最后的 安全 章节;
Link to Default User 是让用户自己管理自己的号码,如果不需要,则选 None

点击 Submit 后,保存成功。用同样的方法再创建一个用户用于测试。

创建完两个用户后,点击右上角的 Apply Config 使配置生效。

11.在 Settings => Asterisk SIP Settings 页面的 General SIP Settings 标签页下面,External Address 一栏填写你的外网IP或者你的外网域名,这里我填写了我的外网IP。Local Networks 中填写你的树莓派所在的子网。RTP Port Ranges 里,填写 1000010100。这里不要使用 20000,测试来看,如果你只是自己用,设置 10100 很稳定。点击 Submit 保存。

8.png

12.切换到 Chan PJSIP Settings 标签页下面,把 tcp 设置为 yes,点击 Submit 保存。
Asterisk 默认使用的是 UDP,为了能保证手机app在后台运行时,可以及时收到来电提醒,需要开启 tcp 通信。

9.png

13.去自己的路由器上,设置端口映射,需要打开 506010000-10100,可以参考下图

4.png

5.png

14.去 http://www.linphone.org/ 下载 Linphone 到你的手机和电脑上,如下图分别用刚才新建立的两个账号登陆两个客户端。

1.jpeg

2.jpeg

3.jpeg

a1.png

a2.png

a3.png

a4.png

现在从手机上,拨打 102 ,如果以上设置没有问题的话,电脑上就能响铃,接起来,两边听一下,看看有没有什么问题。如果有一方听不到,很可能是端口映射的问题,重新检查下配置。端口映射这里偶尔会有莫名奇妙的问题。

配置GSM,实现呼入和呼出

1.把 SIM 卡插入 3G 卡托,把 3G 卡托插到树莓派或者 USB HUB 上。

2.SSH 连接到树莓派后,执行下面的命令安装 dongle 扩展

1
root@raspbx:~# install-dongle

其中①输入你插入 3G 卡托里的手机卡号,②输入你要准备接收短信的邮箱地址,③如果你不想转发短信留空即可。

安装到最后,会再问你是否需要安装网页界面的发短信工具(即访问地址就是 http://raspbx_ip/sms),按照提示输入即可

1
2
3
Would you like to install a webpage for sending SMS with
chan_dongle? (http://raspbx/sms/) [y/N] y
Enter password for SMS page: 123456

注意:安装 dongle 扩展需要翻墙

3.回到网页配置界面,依次访问 Connectivity => Trunks => Add Trunk => Add Custom Trunk

b2.png

4.在 General 标签页下面,设置一个 Trunk NameOutbound CallerID 中填写你的手机号

b33.png

5.在 custom Settings 中设置 dongle/dongle0/$OUTNUM$

b44.png

这里如果你只是插了一个 3G Dongle,那么就是默认 dongle0,如果你设备上插了多个设备,你需要在命令行下输入一下命令,查看下所有的 Dongle

1
2
3
root@raspbx:~# asterisk -rx "dongle show devices"
ID Group State RSSI Mode Submode Provider Name Model Firmware IMEI IMSI Number
dongle0 0 Free 6 5 4 CHN-CUGSM E1750 11.126.10.00.00 359767033517971 460090019804894 +8617xxxxxxx44

6.点击 Submit 保存设置,然后点击右上角的 Apply Config 使配置生效。

7.从 Connectivity => Outbound Routes => Add Outbound Route 中,在 Route Settings 下面填写一个 Route Name,在 Trunk Sequence for Matched Routes 中选择刚才添加的 Trunk

b3.png

6.切换到 Dial Patterns 标签下,按照下图来配置拨号规则,这里配置的规则是,匹配所有0开头的电话号码,把所有0开头的号码,去除开头的0后,转发到我们设置的那个 Trunk 上,进行呼出操作。

b4.png

7.点击 Submit 保存配置,点击右上角 Apply Config 使配置生效。生效后,你现在可以用你的 App 进行外呼操作了,只要在要拨打的电话前加拨0,即可完成外拨。

8.在 Connectivity => Inbound Routes => Add Inbound Route => General 下,配置 Set Destination ,选择 Extension,从已经添加的 Extension 中,选择一个即可。点击 Submit 保存配置,点击右上角 Apply Config 使配置生效。生效后,你可以拨打你的 3G Dongle 中的手机卡号,如果顺利,你手机上的 App 将会接到这个呼入操作。

d1.png

d2.png

配置 Email,测试收发短信

1.输入如下命令进入 Email 配置界面:

1
# dpkg-reconfigure exim4-config

2.选择 internet site; mail is sent and received directly using SMTP

e1.png

3.配置你的发信域名

e2.png

4.保持默认值

e3.png

  1. 配置为你的发信域名

e4.png

6.以下几步保持默认值

e5.png

e6.png

e7.png

e8.png

e9.png

7.该步输入 root

e10.png

8.完成发信配置后,使用 send_test_email <your_email> 命令进行发信测试。打开你的邮箱,检查垃圾箱,100%的会被拦截,像我用的腾讯的企业邮,在 自助查询 中可以找到拦截信息,为了收信顺利,把你上面配置的发信域名加入邮箱的域名白名单即可。

e11.png

9.用手机给自己 3G Dongle 里的手机卡发条短信,应该很快就能收到邮件了,

10.如果想要发送短信的话,我们可以通过 Web 页面进行,访问 http://your_raspbx_ip/sms,会提示你输入密码,这个密码即为你安装 Dongle 扩展的时候输入的那个密码,登陆后如下所示

注意:收件人手机号一定要加国号

设备安全!!!!!

先给大家看一个截图,

s1.png

这是目前我的设备被暴力破解的情况。

请一定重视安全问题

再附上我之前的悲惨遭遇:https://www.v2ex.com/t/394297#reply11

1.首先,你的 Extension 一定要给各个账号配置超强的密码

2.其次,使用 Fail2ban 来防暴破。

1
# install-fail2ban

3.安装 Fail2ban 后,程序会自动启动,我们需要调整下配置,打开 /etc/fail2ban/jail.conf 文件,搜索 [asterisk],找到 maxretry 项,修改为 2,就是说密码输入错2次,就会被 Fail2ban 拦截。再搜索下 bantime,修改为 604800。配置好后,意味着有人要是输入错两次密码,那么这个人的 IP 就会被屏蔽一周。保存后,执行 systemctl restart fail2ban 重启服务使配置生效。

后记

本来计划争取半天写完,结果写了一天半。最初其实是计划写一本 《面向菜鸟的 Asterisk 教程》,把各种好玩的功能写进去的,让菜鸟也能轻松的用上牛逼的 Asterisk 。不过还是感觉自己的水平和能力没有达到,于是放弃了。

目前这篇教程里还未涉及的我已经测试可用的功能,还有 语音信箱电话会议电话组。其中 语音信箱 功能还是很赞的,可以在自己未接听电话的时候,自动把呼入转接到 语音信箱,让给你打电话的人给你留言,留言还可以配置发送到你的邮箱。这些功能有机会我再写教程吧。

目前这套方案,收发短信很稳定,语音通话的话,会受到你在国外手机网络连接回你国内家里的网络情况的影响。按照两年前去欧洲的时候我的测试来看,当时在瑞士的时候,连接回国内打电话大约会有将近1秒的延时,勉强可以通话。

如果有什么疑问,可以在本帖下面留言,我收到 回复提醒 后,会尽力第一时间给出答复。

最近运行了一个见证人节点,并且发布了 见证人公告,欢迎各位给我投上一票,投票链接:https://v2.steemconnect.com/sign/account-witness-vote?witness=ety001&approve=1

为了成为 见证人,我搜索了很多的资料,中文资料目前应该是没有,基本上都是英文的,并且每一篇都只是介绍了某一点,尤其是如何把自己的账号升级为见证人,这方面的资料几乎就没有。这里我将介绍下如何快速搭建成为见证人。(为了重现这个过程,我拿我的另外一个账号 liuye 来重新走一遍流程)

注意1:教程将以Ubuntu16.04作为操作环境,如果你用其他的Linux系统,需要自己解决各种依赖等问题。

注意2:目前网上建议最小内存 32GB,最小硬盘 100GB(当前时间:2018.01.30)为了写这个教程,现买了几个小时的 VPS 用来测试。小内存似乎也可以跑,文末总结有彩蛋。

把账号升级为见证人

目前最便利的方法就是使用 Conductor 了。建议把 Conductor 安装在本地,毕竟这一步需要导入你的账号信息,如果在服务器操作,可能安全度不高。另外,确保你的本地安装了 Python3

1.安装必要的依赖

1
sudo apt install libffi-dev libssl-dev python3 python3-dev python3-pip

2.安装 steem-python

1
pip3 install -U git+git://github.com/Netherdrake/steem-python

3.安装 conductor

1
pip3 install -U git+https://github.com/Netherdrake/conductor

4.使用 steem-python 创建本地钱包,并导入你的账号

1
$ steempy addkey

弹出下面的提示

1
Private Key (wif) [Enter to quit]:

在这里输入你账号的活跃权限的私钥,在你的 steemit 的网站钱包页面的权限中可以找到。
输入完,回车,会提示下面的信息

1
Please provide a password for the new wallet

这里输入一个你自己的密码,用于加密你本地的钱包,假如这里我们设置的是 123456
当再次弹出 Private Key (wif) [Enter to quit]: 时表明添加成功,直接回车退出。

5.初始化见证人

1
conductor init

回车后会依次让你输入下面的内容

1
2
3
4
5
6
7
8
What is your witness account name?: liuye
Witness liuye does not exist. Would you like to create it? [y/N]: y
What should be your witness URL? [https://steemdb.com/witnesses]: https://steemit.com/@liuye
How much do you want the account creation fee to be (STEEM)? [0.500 STEEM]: 0.200 STEEM
What should be the maximum block size? [65536]:
What should be the SBD interest rate? [0]:
BIP38 Wallet Password:
Witness liuye created!

其中 account creation feemaximum block sizeSBD interest rate这几个参数我也不清楚具体干什么的,
我是按照多数见证人的设置来配置的,其中注意 account creation fee 的格式。另外那个 BIP38 Wallet Password 就是上一步里设置的钱包密码,即那个 123456

6.生成打包区块所要用的公私钥对

1
conductor keygen

这一步生成的公钥将用来激活你的见证人,生成的私钥将配置在服务器节点的 config.ini 文件中。
比如这里我生成的是

1
2
3
4
5
+-----------------------------------------------------+-------------------------------------------------------+
| Private (install on your witness node) | Public (publish with 'conductor enable' command) |
+-----------------------------------------------------+-------------------------------------------------------+
| 5JEREu41d6zdBsFHjKx3PumyHMhydUH5DCPFejRiBTyQLg3rGgt | STM6fhWKaF4okgbjeAZrQg7mc7fNUKT7BtyevHAF9Qtfe666RDaEp |
+-----------------------------------------------------+-------------------------------------------------------+

7.激活见证人

1
conductor enable STM6fhWKaF4okgbjeAZrQg7mc7fNUKT7BtyevHAF9Qtfe666RDaEp

回车后会要求输入钱包密码,等看到一堆信息后,如果 block_signing_key 里是你设置的公钥,
那么就激活成功了。

8.临时关闭见证人

1
conductor disable

按照提示输入完信息后,当看到一堆信息后,其中的 block_signing_key 变为 STM1111111111111111111111111111111114T1Anm 则表明见证人临时关闭成功。

如果目前你的节点不在运行,则需要临时关闭见证人,否则如果轮到你出块了,而你不在线,则将记录一次你丢块。(PS: 通过我这一周的观察,目前我的这些票数,完全轮不到我出块,所以关不关掉都是一个样。。。😂)

部署见证人节点

我自己搭建见证人节点的时候,是使用的官方的 Docker 镜像。
本教程则使用更傻瓜化的一个 Docker 镜像 来完成。

再次注意:服务器环境是ubuntu16.04

1.更新系统,安装依赖,获取 steem-docker 的安装脚本。

1
2
3
4
sudo apt update
sudo apt install git curl wget
git clone https://github.com/Someguy123/steem-docker.git
cd steem-docker

2.安装 Docker,如果你的系统目前已经安装,则跳过该步

1
./run.sh install_docker

3.拉取 steem-docker 镜像

1
./run.sh install

4.同步区块数据,目前区块数据大约23GB,该步是从大佬@gtg 维护的节点下载已经打包好的区块数据(同步和解压都需要很久,尤其是解压)。

1
./run.sh dlblocks

如果你想跳过下载这一步,而是想直接通过 P2P 网络来同步区块数据,那么在执行第7步之前,可以修改一下 run.sh 的 170 行,

我们删除掉,最后的那个 --replay 参数,然后执行 ./run.sh replay
通过读取日志,看到有区块数据同步后,再次修改 run.sh 的 170 行,把刚才去掉的参数再加回来,加回参数后,再执行 ./run.sh replay 即可。
如果提示类似下面的错误

1
Error response from daemon: You cannot remove a running container c083355ec3960722bee080cff5c1bb13c225f5b9a3e0ae8ea63b4f73ce531992. Stop the container before attempting removal or force remove

执行下面的命令后再执行 ./run.sh deplay,其中 c08 是报错中提到的那个 container id 的头几位

1
docker stop c08

5.调整内存。由于要使用 /dev/shm 来作为 shared-file-dir,而默认 /dev/shm 是机器内存的一半,为了更好的利用内存,我们需要把这个内存调大,我的服务器是32GB的,因此我调到30GB,留下2GB给系统自己。(啥是 shm。)

1
sudo ./run.sh shm_size 30G

6.修改 config.ini 配置文件

1
vim data/witness_node_data_dir/config.ini

只需要参照下面的内容修改几项即可,

1
2
3
4
5
p2p-endpoint = 0.0.0.0:2001 # 做种子
shared-file-size = 30G
shared-file-dir = /shm # 如果注释掉这行,在小内存机器上也可以跑
witness = "liuye" # 这里填写你的 steem 账号,注意要加双引号!!
private-key = 5JEREu41d6zdBsFHjKx3PumyHMhydUH5DCPFejRiBTyQLg3rGgt # 这里填写 conductor 生成的私钥,不需要引号

7.启动见证人节点

1
./run.sh replay

运行成功后,可以通过 ./run.sh logs 命令,查看 Docker容器 的运行情况,如图

Log 信息中出现见证人信息了,就代表配置成功了。等待区块链同步到最新后,显示类似下面的内容时,就一切正常了,这时别忘了用 conductor 激活见证人。

8.发布见证人公告到 witness-category 下面,以表示你开始了见证人之旅。写一写你能为社区做啥,为啥大家要给你投票之类的。

关于喂价

见证人除了打包这个工作外,还有一个重要的工作就是给系统提供喂价。
目前有好几个版本的喂价脚本, 这里我们使用 conductor 提供的喂价功能即可。

1
conductor feed

第一次运行会出现类似的错误提示

1
2
3
4
5
6
7
8
9
10
11
BIP38 Wallet Password: 
Tue Jan 30 21:18:48 2018
Old Price: 0.000
New Price: 5.165

Current STEEM price: 5.165 USD
Current SBD price: 5.767 USD
Quote: 1.000 STEEM

Spread between prices: 100.000%
Possibly invalid spread (100.00%), ignoring...

查看源代码发现,之所以 ignoring 是因为我们目前在区块上存储的喂价是0,也就是我们还没有提供过喂价,这就导致新旧价格差价过大,即 Spread between prices 过大,超过了代码中设置的 20%,因此被忽略了。这应该是这个喂价程序的一个缺陷,没有考虑第一次喂价更新。

所以我们需要手动使用 Python 完成第一次喂价更新。在终端中打开 Python3,然后按照下面的命令进行输入:

1
2
3
4
5
6
7
8
Python 3.6.3 (default, Oct 24 2017, 14:48:20) 
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from steem import Steem
>>> steem = Steem()
>>> steem.commit.witness_feed_publish(5.165, quote=1.000, account="liuye")
Passphrase:
{'ref_block_num': 33686, 'ref_block_prefix': 2156333139, 'expiration': '2018-01-30T13:37:05', 'operations': [['feed_publish', {'publisher': 'liuye', 'exchange_rate': {'base': '5.165 SBD', 'quote': '1.000 STEEM'}}]], 'extensions': [], 'signatures': ['202c413bf800c51e583a30687954fa5e77b052bd90e3e4834d5fa82a817121ebb40677fbf1351abcd70e656eb7fc97e16e236aa5092960ec87e6f0a0531ba982b6']}

其中 witness_feed_publish 的参数中,5.165Current STEEM price: 5.165 USDquoteQuote: 1.000 STEEM

完成手动更新后,再次使用 conductor feed 执行就成功了。

如果想要使用 Docker 化的 conductor,可以参考 这里,我自己封装了一个。

总结

前前后后连写加调试,完成这篇教程花了有那么几个小时,这应该是目前中文版教程里最全的了,没有之一。

这里有个小技巧,如果你内存不够,在配置文件中不要用 /dev/shm 作为 shared-file-dir,节点依然可以运行,也就是说可以注释掉 shared-file-dir = /shm。之所以把这个放在最后说,是因为我并没有完全测试这种情况。其他人貌似都是用 /dev/shm 来作为 shared-file-dir 的。

总的来说,搭建见证人节点就是会者不难,难者不会。虽然见证人节点的资源消耗不及全节点,但是也是够费资源的。我目前并不理解,为何见证人节点需要同步全量数据,难道只获取目前区块链全部数据的最近25%的数据,不能完成打包工作吗?看来这个还有待等到进一步去看源代码的时候思考。

下午购买了新的vps,从原来的 1核1G内存100G硬盘100M带宽1TB流量 升级到 2核6G内存500G硬盘100M带宽流量不限,为了搭建 steem-mysql 我也是拼了血本了。

为了转移已经同步好的数据库文件,大约有33G,一开始大意了,使用了 scp ,然后就放在那里传输,也忘记开个 screen ,中间打了个盹,等醒了的时候发现,服务器断开连接了😂。由于 scp 不带断点续传,所以说已经传完的60%多的数据就是白传了🤣🤣🤣🤣。

大文件的传输还是得靠 rsync,自己大意了。rsync 除了支持断点续传外,还可以进行 gzip 压缩传输,这样效率更高,以下是两者的对比:

scp:

1
2
3
root@steem-mysql:~# scp /data/mysql.tar [email protected]:~/
[email protected]'s password:
mysql.tar 18% 6158MB 6.9MB/s 1:05:55 ETA

rsync:

1
2
3
4
5
root@steem-mysql:~# rsync -avzhP /data/mysql.tar  [email protected]:~/
[email protected]'s password:
sending incremental file list
mysql.tar
13,484,294,144 38% 21.12MB/s 0:16:30

如果 ssh 端口换了,那么需要加个参数

1
rsync -avzhP -e 'ssh -p 1234' /data/mysql.tar  [email protected]:~/

另外,为了防止网络不稳定,在执行一些用时比较久的任务时,建议使用 screen 新开一个 session 来进行耗时较久的任务:

1
$ screen -S ws   # ws是自己定义的一个session名字

如果中途网络断开了,我们重新连入服务器,只需要执行

1
$ screen -r ws

即可恢复刚才的 session.

如果有多个 session 的话,可以使用下面的命令查看有哪些 session:

1
$ screen -ls

Portainer is a simple UI management for docker. It’s easy to use and all your resources will show you friendly. It’s very light especially using a VPS which has only 512MB RAM.

In this tutorial, we will make a LNMP server over the docker container by Portainer.

What Will I Learn?

  • You will learn how to setup portainer
  • You will learn how to create a custom network with the docker
  • You will learn how to create a container

Requirements

  • Ubuntu 16.04 (64-bit)
  • Base bash knowledge
  • Base docker knowledge
  • Built a normal LNMP environment before

Difficulty

  • Intermediate

Tutorial Contents

Setup Portainer

1.Create a volume to save the portainer data. You also can bind a folder.

1
$ docker volume create portainer_data

2.Run the Portainer docker.

1
$ docker run -d -p 9000:9000 --name portainer -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data --restart always portainer/portainer
  • -d means run as daemon
  • -p 9000:9000 means making a port map. Portainer needs port 9000 opening.
  • -v /var/run/docker.sock:/var/run/docker.sock This parameter is important if you want portainer to manage your local docker.

3.Visit http://localhost:9000 in your browser and input your username and password to create the administrator user.

1.png

4.In next step select the Local option and press Connect button to finish setup.

2.png

5.When you see the main page, the installation is over.

3.png

Create a new network

The container link is out of date now. The portainer doesn’t support the container link any more. So we need to create a new bridge network and bind static IPs to every container we create. Then each container can communicate with each other through the static IPs.

1.Get in the Networks page and click the Add network button.

4.png

2.Input the required information like the snapshot and then click the Create the network button.

5.png

Add MariaDB container

In this tutorial, we use the App Template to create the MariaDB container.

1.Create a folder to storage the MariaDB database file

1
$ sudo mkdir -p /data/mariadb

2.Enter the App Template page and select the MariaDB option.

6.png

3.Input required information with snapshot (When you clicked the Deploy the container button, you need waiting a while. Because docker is pulling the portainer image.)

7.png

4.Because the App Template doesn’t set the static IP, we need set it with editing the container configurations manually. Open the container detail page:

8.png

5.Click the Duplicate/Edit button

9.png

6.Find the Advanced container settings section, select the Network tab, input a static IP into the IPv4 address, click Deploy the container.

10.png

7.Portainer will mention you whether if to replace the original container. Click Replace.

11.png

8.If we want to connect to the database on the host, we can run this command

1
$ docker run -it --rm --name mariadb_client --network mynet mariadb /usr/bin/mysql -h 172.20.0.2 -uroot -p
  • --network mynet is needed. You must put the client container into your MariaDB server container’s network.
  • --rm will destroy this client container when it ends.

OR

1
$ docker exec -it mariadb /usr/bin/mysql -h 172.20.0.2 -uroot -p

Add nginx container

In this example, we use the App Template to create the nginx container.

1.Deploy a nginx container from App Template and bind container /data to host /data.

12.png

2.Open the Containers list and find the container you just created and click the third icon to get in the container console.

13.png

3.Run this command to copy nginx configurations to your host.

1
# cp -r /etc/nginx /data

14.png

4.On the host terminal run this command

1
$ sudo cp -r /data/nginx /etc/nginx

5.Edit the exist nginx container with these snapshots

16.png

17.png

18.png

Add a php-fpm7 container

1.Create a php-fpm7 image
I refer to this repo to create the image. This image is based on Alpine so it’s light enough.

1
2
$ git clone https://github.com/Yavin/docker-alpine-php-fpm.git
$ cd docker-alpine-php-fpm

2.Edit the php-fpm.conf:

1
2
3
4
5
6
7
8
9
10
11
[www]
user = nobody
group = nobody
listen = [::]:9000
chdir = /data/wwwroot # Change the chdir
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
catch_workers_output = Yes

3.Build image

1
$ docker build -t php-fpm7:latest .

4.Add a new container

19.png

5.Configure step by step with thees snapshots:

20.png

21.png

22.png

23.png

Final Config

1.At last, we need to edit the /etc/nginx/conf.d/default.conf on host like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ sudo vim /etc/nginx/conf.d/default.conf

server {
listen 80;
server_name localhost;

location / {
root /data/wwwroot/default;
index index.html index.htm index.php;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
root /data/wwwroot/default;
fastcgi_pass 172.20.0.4:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

}

2.Create index.php for testing

1
2
$ sudo mkdir /data/wwwroot/default
$ sudo echo "<?php phpinfo();?>" > /data/wwwroot/default/index.php

3.Restart nginx container

24.png

Visit the test page

25.png

Summary

Using dockerized apps is a trend. If you want to run dockerized apps on your personal VPS, Portainer is a good choice. It’s easy and light.


Portainer 是一个为 Docker 设计的简易 UI 管理界面. 通过 Portainer 可以轻松管理你的 Docker 的各种资源. 它是轻量级的, 你甚至可以在一台只有 512MB 内存的 VPS 上部署使用.

在这个教程中, 我们将通过使用 Portainer 部署一套 LNMP 环境, 来学习如何使用 Portainer.

将会学到?

  • 你将学到如何安装 Portainer
  • 你将学到如何在 Portainer 中创建自定义的网络
  • 你将学到如何用 Portainer 创建容器

准备工作

  • Ubuntu 16.04 (64-bit)
  • Bash 基础知识
  • Docker 基础知识
  • 曾搭建过普通环境的 LNMP

困难度

  • 中等

教程内容

安装 Portainer

1.创建一个卷来存储 Portainer 的数据, 你同样也可以使用主机的目录来存储

1
$ docker volume create portainer_data

2.使用 Docker 运行 Portainer.

1
$ docker run -d -p 9000:9000 --name portainer -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data --restart always portainer/portainer
  • -d 已后台方式运行
  • -p 9000:9000 映射容器9000端口.
  • -v /var/run/docker.sock:/var/run/docker.sock 映射出 docker socket 使 Portainer 容器可以管理 Docker.

3.使用浏览器访问 http://localhost:9000 进入安装界面, 输入用户名和密码完成管理员创建.

1.png

4.选择 Local 选项后点击 Connect 按钮完成安装.

2.png

5.当你看到管理主页的时候, 安装完成.

3.png

创建新的网络

container link 连接容器的方法已经过时了, 并且 Portainer 也不支持 link. 因此为了让容器间可以通讯, 我们需要建立自定义网络, 并手动分配静态IP给每个容器.

1.进入 Networks 页面并点击 Add network 按钮.

4.png

2.按照截图提示输入必要信息并点击 Create the network 按钮.

5.png

添加 MariaDB 容器

在这个教程中我们使用 App Template 来创建 MariaDB 容器.

1.创建一个目录来存储数据库数据

1
$ sudo mkdir -p /data/mariadb

2.进入 App Template 页面后选择 MariaDB 选项.

6.png

3.按照截图填写配置信息 (当你点击完 Deploy the container 按钮后, 你需要等待一段时间, 因为 Docker 正在后台帮你拉取镜像.)

7.png

4.由于 App Template 没有设置静态IP, 我们需要手动配置下. 打开容器的详情页:

8.png

5.点击 Duplicate/Edit 按钮

9.png

6.找到 Advanced container settings 部分, 选择 Network 选项卡, 在 IPv4 address 中输入一个静态IP, 点击 Deploy the container 完成.

10.png

7.Portainer 将会提示你是否替换原有容器. 点击 Replace.

11.png

8.如果想在主机上连接访问数据库, 可以执行下面的命令:

1
$ docker run -it --rm --name mariadb_client --network mynet mariadb /usr/bin/mysql -h 172.20.0.2 -uroot -p
  • --network mynet 这个选项是必须的, 你必须把客户端容器放置在服务端容器的网络中才可以访问到.
  • --rm 这个配置可以使这个容器在执行完毕后立即删除.

或者

1
$ docker exec -it mariadb /usr/bin/mysql -h 172.20.0.2 -uroot -p

创建 Nginx 容器

在本教程中我们使用 App Template 创建 Nginx 容器.

1.从 App Template 中部署一个 Nginx 容器, 并把容器中的 /data 绑定到主机的 /data 上.

12.png

2.打开 Containers 列表, 找到你刚才创建的容器并点击第三个图标, 进入容器的 console 界面.

13.png

3.执行下面的命令, 把容器中 Nginx 的配置文件复制到主机下.

1
# cp -r /etc/nginx /data

14.png

5.在主机上执行下面的命令

1
$ sudo cp -r /data/nginx /etc/nginx

6.按照截图的指示修改容器配置, 完成 Nginx 容器部署

16.png

17.png

18.png

创建 php-fpm7 容器

1.创建一个 php-fpm7 的镜像
我参考了这个 repo 来创建镜像. 这个镜像的好处是基于 Alpine 创建, 非常轻量.

1
2
$ git clone https://github.com/Yavin/docker-alpine-php-fpm.git
$ cd docker-alpine-php-fpm

2.修改 php-fpm.conf:

1
2
3
4
5
6
7
8
9
10
11
[www]
user = nobody
group = nobody
listen = [::]:9000
chdir = /data/wwwroot # 修改 chdir
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
catch_workers_output = Yes

3.构建镜像

1
$ docker build -t php-fpm7:latest .

4.创建新容器

19.png

5.按照截图一步一步操作, 完成容器创建:

20.png

21.png

22.png

23.png

最后的配置

1.最后我们需要修改下主机上的 Nginx 配置文件 /etc/nginx/conf.d/default.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ sudo vim /etc/nginx/conf.d/default.conf

server {
listen 80;
server_name localhost;

location / {
root /data/wwwroot/default;
index index.html index.htm index.php;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
root /data/wwwroot/default;
fastcgi_pass 172.20.0.4:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

}

2.创建一个测试首页 index.php

1
2
$ sudo mkdir /data/wwwroot/default
$ sudo echo "<?php phpinfo();?>" > /data/wwwroot/default/index.php

3.重启 Nginx 容器

24.png

在浏览器中访问测试页面

25.png

总结

使用 Docker 化应用是一个趋势. 如果你想在你的个人 VPS 上运行 Docker 化的应用, Portainer 是一个不错的选择, 因为它使用简单并且轻量.

简介

VundleVim Bundle 的简称,是为了使 Vim 的插件更便于管理,如果你使用过 Vim ,那么你也一定对于 Vim 的插件管理很头疼。现在可以体验下 Vundle 给我们带来的使用便利。

快速全新安装(Mac or Linux)

1. 清除掉原有配置,如果需要备份,请先备份

1
~ » rm -rf .vim .viminfo .vimrc

2. 安装 Vundle

1
~ » git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim

3. 创建 .vimrc 并添加以下 Vundle 的配置信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
set nocompatible              " be iMproved, required
filetype off " required

" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
" alternatively, pass a path where Vundle should install plugins
"call vundle#begin('~/some/path/here')

" let Vundle manage Vundle, required
Plugin 'VundleVim/Vundle.vim'

" Add your plugins to this place 在这里添加你的插件

" 在这行前添加你的插件
call vundle#end() " required
filetype plugin indent on " required
" To ignore plugin indent changes, instead use:
"filetype plugin on
"
" 以下是常用命令
" :PluginList - lists configured plugins
" :PluginInstall - installs plugins; append `!` to update or just :PluginUpdate
" :PluginSearch foo - searches for foo; append `!` to refresh local cache
" :PluginClean - confirms removal of unused plugins; append `!` to auto-approve removal
"
" see :h vundle for more details or wiki for FAQ
" 在该行后添加自己的配置信息

4. 安装插件

启动 Vim 然后运行 :PluginInstall,底部状态栏显示 Done 即为安装完毕,如图
setup_success

使用说明

1. 想要安装新的插件

.vimrc 中的 Plugin 'VundleVim/Vundle.vim'call vundle#end() 之间插入你想要增加的插件信息,常见的几种语法如下:

1
2
3
4
5
6
7
8
" 插件托管在 Github 上的
Plugin 'tpope/vim-fugitive'
" 插件托管在 http://vim-scripts.org/vim/scripts.html 上的
" Plugin 'L9'
" 插件托管在非 github 上的
Plugin 'git://git.wincent.com/command-t.git'
" 插件是在自己本地的
Plugin 'file:///home/gmarik/path/to/plugin'

比如我要安装 NERDTree 插件,它的 Github 地址是 https://github.com/scrooloose/nerdtree,那么添加的配置信息如下:

1
Plugin 'scrooloose/nerdtree'

然后启动 Vim ,执行 PluginInstall 即可完成安装。

2. 增加自己的配置信息

如果想要增加自己的配置信息的话,只要在 Vundle 的配置信息之后增加即可,以下是我的自定义配置信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
colorscheme peachpuff
set guifont=Monaco:h10 " 字体 && 字号
set expandtab " 设置tab键换空格
set tabstop=4 " 设置tab键的宽度
set shiftwidth=4 " 换行时行间交错使用4个空格
set autoindent " 自动对齐
set backspace=2 " 设置退格键可用
set cindent shiftwidth=4 " 自动缩进4空格
set smartindent " 智能自动缩进
set ai! " 设置自动缩进
set nu! " 显示行号
set showmatch " 显示括号配对情况
"set mouse=a " 启用鼠标
set ruler " 右下角显示光标位置的状态行
set incsearch " 查找book时,当输入/b时会自动找到
set hlsearch " 开启高亮显示结果
set incsearch " 开启实时搜索功能
set nowrapscan " 搜索到文件两端时不重新搜索
set nocompatible " 关闭兼容模式
set vb t_vb= " 关闭提示音
"set cursorline " 突出显示当前行
hi CursorLine cterm=NONE ctermbg=darkred ctermfg=white
hi CursorColumn cterm=NONE ctermbg=darkred ctermfg=white
set hidden " 允许在有未保存的修改时切换缓冲区


syntax enable " 打开语法高亮
syntax on " 开启文件类型侦测
filetype indent on " 针对不同的文件类型采用不同的缩进格式
filetype plugin on " 针对不同的文件类型加载对应的插件
filetype plugin indent on " 启用自动补全

set writebackup " 设置无备份文件
set nobackup
set autochdir " 设定文件浏览器目录为当前目录
set nowrap " 设置不自动换行
set foldmethod=syntax " 选择代码折叠类型
set foldlevel=100 " 禁止自动折叠

set laststatus=2 " 开启状态栏信息
set cmdheight=2 " 命令行的高度,默认为1,这里设为2


" 设置编码
set fenc=utf-8
set encoding=utf-8
set fileencodings=utf-8,gbk,cp936,latin-1
" 解决consle输出乱码
language messages zh_CN.utf-8

3. 对自己的 .vimrc 进行版本管理

大致配置好以后,可以把自己的 .vimrc 加入到自己的某个 Github 库中进行版本管理。然后做 ln 到自己的家目录。

0%