Fabric 2.x 使用

Fabric 在升级 2.x 之后,几乎就是重写了。很多以前的用法都变了,然后在 1.x 时代,本地和远程都是用一套代码处理,但是 2.x 的时候将 local 处理部分和远程处理部分分别拆分为 fab 和 invoke 了,拆分的理由可以参考这里

以前 Fabric 是不支持 Python 3 的,升级之后的版本可以完美支持 Python 3,然后下面是 Fabric 2.x 的升级理由:

  • Python 3 compatibility support 2.7 and 3.4+
  • Thread-safe
  • API reorganized around fabric.connection.Connection
  • Command-line parser overhauled to allow for regular GNU/POSIX style flags and options on a per-task basis (no more fab mytask:weird=custom,arg=format);
  • Task organization is more explicit and flexible
  • Tasks can declare other tasks to always be run before or after themselves;

更多关系 1.x 和 2.x 的对比可以参考这个网址

忘记 1.x 的一切,然后从头开始


2018-06-19 fabric , python , deploy

《分布式服务架构:原理、设计与实战》读书笔记

总得来说这本书按照微服务的各个内容介绍了一遍,但是只适合入门,并不适合深入了解。看完可以对什么是微服务有一个大致的了解,对于自己实现一个微服务架构还是需要更多的阅读。

第 1 章 原理

微服务架构的目的是为了解决传统单体应用在业务急剧增长时遇到的水平扩展问题。通过拆分服务,将微服务系统中的服务划分明确的职责,做到低耦合,高内聚。

微服务交互模式

  1. 读者容错处理
  2. 消费者驱动契约模式,服务提供者向所有消费者承诺遵守的约束,一旦消费者把具体期望告诉提供者,提供者无论在什么时间和场景下,都不应该打破契约。

两个概念:

  • 水平扩展,扩展单节点
  • 垂直扩展,功能拆分,专业的人做专业的事,将复杂功能拆分为多个单一,简单功能的组合

SOA 面向服务的架构

常见的 SOA 服务化架构

  • Dubbo
  • Thrift

第 2 章 分布式系统一致性问题

分布式系统 CAP 原理

  • Consistency 一致性,同一时刻,所有副本数据一致
  • Availablity 可用性
  • Partition tolerance 分区容忍性,可容忍部分数据丢失,但系统仍然能够继续工作

三者不能同时兼得。

BASE 思想,满足 CAP 原理,牺牲强一致性获得可用性,通过最终达到一致性来满足业务

  • BA Basically Available 基本可用
  • Soft State 软状态,状态可以在一段时间内不同步
  • Eventually Consistent,最终一致性,在一定时间窗口内达到一致

解决方案:

  • 两阶段提交协议
  • 三阶段提交协议
  • TCC 协议

第 3 章 服务化系统容量评估末日性能保障

容量:按照峰值 5 倍冗余计算

MySQL

  • 单端口读 1000/s
  • 单端口写 700/s
  • 单表容量 5000 万

Redis

读写 40000/s

Kafka 单机 读 30000/s 写 5000/s

然后书上介绍了一些压测工具,ab,jmeter,mysqlslap,sysbench,dd,loadRunner,hprof 等等

第 4 章 日志

首先介绍了一些日志框架,然后是 ELK。

第 5 章 调用链

这部分没有细看,先开始介绍了 APM 的功能和作用,然后介绍了 Dapper 论文里面提到的调用链跟踪原理。

第 6 章 线上问题

海恩法则:

每一次严重事故的背后,必然有 29 次轻微事故和 300 起未遂先兆及 1000 起事故隐患。

墨菲定律,这个条太熟悉了,星际穿越中就提及了

如果有两种或两种以 上 方式去做某件事情,而选择其中一种方式将导致灾难,则必定有人会做出这种选择。

墨菲定律实际上是个心理学效应,如果你担心某种情况会发生,那么它更有可能发生,久而久之就一定会发生。

后面介绍了 java 自带的调试工具,还有一些 Linux 下的常用命令。

后面作者举了一个真实的线上问题解决思路。

第 7 章 服务容器化

主要就是介绍 Docker 了。

第 8 章

关于敏捷开发,持续集成,持续交付和持续部署。然后是一些常用的开发,运维工具。


2018-06-18 distributed-system , reading , book

威联通折腾篇五:安装 Transmission 下载 BT

这一篇讲在威联通上安装和使用下载工具 – Transmission。

Transmission 是一个 BT 客户端,提供了 Web 和命令行界面,非常适合在威联通机子上跑。威联通自身的 Download Station 根本无法用,而迅雷和百度也基本无法用。只能尝试一下这个方法了。

安装

如果看过之前的文章,应该知道威联通第三方的应用市场 QNAP CLUB,在其中直接能够找到 QTransmission。安装完成之后用户名密码是 qnap 和 qnap。

配置文件路径:

  • /opt/QTransmission/etc
  • /share/CACHEDEV1_DATA/.qpkg/QTransmission/etc

为什么有两个路径呢,是因为 opt 目录下的路径其实是一个软链接,指向真实在 /share/CACHEDEV1_DATA/.qpkg/QTransmission 的目录。

如果要修改 WEB 界面的端口,需要同时修改 /mnt/HDA_ROOT/.config/qpkg.conf 里面 QTransmission 配置的端口。

配置

安装完成后直接在威联通 WEB 界面上点击进入,然后使用 qnap - qnap 登录。设置限速、关闭 DHT,然后在路由器上做端口转发,保证 51413 端口开放。

使用 vi 修改配置 vi /share/CACHEDEV1_DATA/.qpkg/QTransmission/etc/settings.json,需要注意的是在修改配置的时候,停用 QTransmission,否则再启用 QTransmission 就会恢复到默认配置。

其他常用的配置

"cache-size-mb": 16

然后在威联通中新建共享文件夹,配置下载保存的位置。

"download-dir": "/share/Transmission"

等等。

配置详解见文末。

启动脚本

默认情况下可以尝试使用如下命令来启动和停止。

/etc/init.d/QTransmission.sh start
/etc/init.d/QTransmission.sh stop

问题

如果启动之后 51413 端口在界面上依然显示无法连接,可以尝试等待一段时间再试试。我的实际测试情况是界面上无法连接,但是实际还是能够正常工作。

配置监听文件夹自动下载

在配置中:

"watch-dir": "/share/bt",  # 监听文件夹目录
"watch-dir-enabled": true # 是否监听文件夹

即可

远程控制

配合 Android 上的 Transdroid 使用,需要开启远程访问控制,如果有固定的访问 IP 段,可以对应的配置,直接禁用下面两个白名单危险系数较高,慎重:

"rpc-whitelist-enabled": false,
"rpc-host-whitelist-enabled": false,

Transdroid

Transmission 配置详解

打开 Transmission 的配置能看到非常多的配置选项,这里列举一下重要的配置:

"alt-speed-up": 500, # 限速时段上传限速值
"alt-speed-down": 500, # 限速时段下载限速值
"alt-speed-enabled": false,
"alt-speed-time-begin": 540,
"alt-speed-time-day": 127, # 时段限速日期(星期几),127 表示每天,更复杂配置参考官网。用 7 位二进制数表示,然后转换成十进制数,0000001 表示周日,1000000 表示周六,0000010 表示周一,0000100 表示周二。如果你只要在周末限速,该数应该 1000001,转换为十进制就是 65
"alt-speed-time-enabled": true, # 启用限速,为 false 时,以上计划配置则不生效,生效时会自动禁用 alt-speed-enabled 配置,二者只能选一个
"alt-speed-time-end": 420, # 限速时段结束时间,这个配置表示的是凌晨零点到开始时间的分钟数,比如 7:00 就是 7*60=420。需要注意的是,该时间是用的 GMT 时间,即北京时间 -8 小时。比如你计划北京时间 7 点 30 分开始,这个数字应该是(7-8+24)*60+30=1410
"bind-address-ipv4": "0.0.0.0", # IPv4 地址绑定,一般不要改动
"bind-address-ipv6": "::", #IPv6 地址绑定,一般不要改动
"blocklist-enabled": true, # 启动白名单,默认不启动,需要启动改为 true
"blocklist-updates-enabled": false,
"blocklist-url": "http://www.example.com/blocklist",
"cache-size-mb": 4, #缓存大小,以 MB 为单位,建议设大一些,避免频繁读写硬盘而伤硬盘,建议设为内存大小的 1/6~1/4
"compact-view": false,
"dht-enabled": false, #关闭 DHT(不通过 tracker 寻找节点)功能,不少 PT 站的要求,但 BT 下载设置为 true 会使得下载更好
"download-dir": "/share/Downloads", #下载的内容存放的目录
"download-queue-enabled": true,
"download-queue-size": 5,
"encryption": 1, # 加密。指定节点的加密模式,默认 1。0 表示关闭 , 0= 不加密,1= 优先加密,2= 必须加密
"lazy-bitfield-enabled": true, # 默认为 true,设置为 true 时可以避免某些 ISP 通过查询完整位段来屏蔽 BT,从而破解部分 ISP 对 BT 的封杀,当然不一定完全有效
"idle-seeding-limit": 30,
"idle-seeding-limit-enabled": false,
"incomplete-dir": "/share/Downloads",  # 临时文件路径
"incomplete-dir-enabled": false,
"inhibit-desktop-hibernation": true,
"lpd-enabled": false, #禁用 LDP(本地节点发现,用于在本地网络寻找节点), 不少 PT 站的要求
"main-window-height": 500,
"main-window-is-maximized": 0,
"main-window-width": 615,
"main-window-x": 337,
"main-window-y": 211,
"message-level": 2,
"open-dialog-dir": "/share/Download",  # 网页对话框打开的根目录
"peer-congestion-algorithm": "",
"peer-limit-global": 240, # 全局连接数
"peer-limit-per-torrent": 60, # 每个种子最多的连接数
"peer-port": 51413, # 传入端口,预设的 port 口
"peer-port-random-high": 65535, # 传入端口随机值范围上限
"peer-port-random-low": 49152, # 传入端口随机值范围下限
"peer-port-random-on-start": false, # 启用随机端口,默认关闭,不建议改为 true
"peer-socket-tos": "default",
"pex-enabled": false, # 是否启用用户交换,默认为 true,关于 PEX,有兴趣的朋友可参考 http://en.wikipedia.org/wiki/Peer_exchange,对于只用 PT 的朋友,可以设为 false, 禁用 PEX(节点交换,用于同已与您相连接的节点交换节点名单), 不少 PT 站的要求
"port-forwarding-enabled": true, # 启用端口转发(uPnP),如果路由支持并且也开启了 uPnP,则路由会自动做端口映射,但是需要注意的是如果内网有几台机器同时使用 transmission,就必须更改 peer-port 值为不一样
"preallocation": 1, # 预分配文件磁盘空间,0= 关闭,1= 快速,2= 完全。建议取 1 开启该功能,防止下载大半了才发现磁盘不够。取 2 时,可以减少磁盘碎片,但速度较慢。
"prefetch-enabled": 1,
"queue-stalled-enabled": true,
"queue-stalled-minutes": 30,
"ratio-limit": 2, # 分享率限制
"ratio-limit-enabled": false, # 启用分享率限制,默认不启用
"rename-partial-files": true, #在未完成的文件名后添加后缀.part,false= 禁用
"rpc-authentication-required": true, # 远程控制需要验证,默认为需要
"rpc-bind-address": "0.0.0.0", # 远程控制地址绑定,允许 IP 通过 RPC 访问,默认值表示任何地址都可以访问
"rpc-enabled": true, # 启用远程控制,默认启用
"rpc-host-whitelist-enabled": true, # 是否开启主机白名单
"rpc-host-whitelist": "", # 白名单,如果需要远程访问,最好配置
"rpc-password": "{cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxaE", #web-ui 的密码,可直接修改,重新运行或者 reload 服务的时候密码会自动 HASH 增加安全性
"rpc-port": 9091, # 默认 web-ui 的 port 口,也是远程控制端口,可自行更改
"rpc-url": "/transmission/",
"rpc-username": "transmission", #默认登入名称,也是远程控制用户名
"rpc-whitelist": "127.0.0.1", # 远程控制白名单,默认值为所有地址,支持通配符*,如 192.168.2.*
"rpc-whitelist-enabled": true, # 启用远程控制白名单,如果启用,则仅仅上面列出的地址可以远程连接
"scrape-paused-torrents-enabled": true,
"script-torrent-done-enabled": false,
"script-torrent-done-filename": "/home/",
"seed-queue-enabled": false,
"seed-queue-size": 10,
"show-backup-trackers": true,
"show-extra-peer-details": false,
"show-filterbar": true,
"show-notification-area-icon": false,
"show-options-window": true,
"show-statusbar": true,
"show-toolbar": true,
"show-tracker-scrapes": true,
"sort-mode": "sort-by-age",
"sort-reversed": false,
"speed-limit-down": 300, #平时的下载限速
"speed-limit-down-enabled": true, #启用平时下载限速
"speed-limit-up": 30, #平时上传限速
"speed-limit-up-enabled": true, #启用平时上传限速
"start-added-torrents": false,
"statusbar-stats": "total-ratio",
"torrent-added-notification-enabled": true,
"torrent-complete-notification-enabled": true,
"torrent-complete-sound-enabled": true,
"trash-can-enabled": true,
"trash-original-torrent-files": false,
"umask": 18,
"upload-slots-per-torrent": 14
"utp-enabled": true, #启用μTP 协议
"watch-dir": "/share/bt",  # 监听文件夹目录
"watch-dir-enabled": false # 是否监听文件夹

跟多的详细配置可以参考官网文档


2018-06-17 qnap , qnap-tutorial , download , bt

威联通折腾篇六:文件同步

文件同步应该算是 NAS 最最基本的一个服务了,但是为什么直到篇六才提到他呢,是因为威联通自带的 QSync ,嗯,虽然能用,但是,没有 Linux 客户端,虽然其他平台客户端 OK,但是作为我主力工作的平台没有同步客户端,只能 smb 挂载。而之前搞 zerotier 同局域网速度不佳,其他 frp 内网穿透 也最多拉一些小文件,完全做不到 Dropbox 那样无缝,无痛。

而到现在,腾讯云上的 NextCloud 已经稳定运行近半年,所以如果在威联通上装上 NextCloud 只要网络访问畅通的情况下,做到所有平台访问 NAS 应该问题不大。而说到文件同步,之前的时候还用过 Resilio Sync 和 Syncthing ,为什么不用这两个呢? 一来前者确实很好用,只要手握 key ,就能够做到随时随地同步,但是这个神器 tracker 被屏蔽了,导致根本无法连接到节点,虽然有人 VPN 搞,但终究是躲猫猫的游戏,故放弃。而 Syncthing 同为开源的点对点同步工具,其实一点都不差,虽然需要用到的客户端 Linux Android 都有,但是终究不全,虽然现在好像已经有了 gtk 版本,但也不是那么好用。关于二者的具体对比可以参考后文。

安装 NextCloud

在 Container Station 中安装 NextCloud 相对比较容易,如果熟悉 Docker 可以直接使用 Docker Compose 文件,如果不熟悉,那直接使用 GUI 也比较方便。

安装步骤简单描述如下:

  1. 打开 Container Station ,选择创建,然后搜索 nextcloud,选择 Docker Hub
  2. 安装官方提供的 NextCloud 镜像。 注:以上两步可以简化为 ssh 登陆后 docker pull nextcloud, 如果熟悉命令行推荐使用命令行下载避免界面可能出现的各种奇怪问题
  3. 等待镜像下载完成,选择从镜像创建容器
  4. 修改名字为 “nextcloud”,CPU 内存等配置自己选择
  5. 高级设置中,网络选择 NAT 模式,并且在下方选择一个合适的端口,比如 20080,这样以后访问 NAS 该端口就转发到 Docker 80 端口
  6. 设置共享文件夹,如果使用 docker 默认的 volume ,那么会存储在一个很深的目录中,这里我选择挂载本机共享文件夹,这边到 File Station 中创建一个共享文件夹 NextCloud(注意给予其他用户访问权限),然后回到设置,新增挂载,然后本地路径选择刚刚创建的共享文件夹,然后挂载路径填写 /var/www/html
  7. 完成创建。稍等片刻就会发现 NextCloud 共享文件夹中多出了很多容器的文件,其中 NextCloud 之后会同步的文件也在其中。

完成容器的创建之后,需要首次登录配置,在容器成功运行之后,在界面中会出现一个链接,http://:20080 这样的形式,点击进入,如果一切都没问题,这边应该会出现 NextCloud 首次安装的配置,需要创建管理员和连接数据库。

这边我选择使用 NAS 宿主机的 MySQL 服务,而不像之前使用 Docker Compose 那样 使用 MySQL 容器,主要是 NAS 上可以方便的使用 phpMyAdmin 来管理。NAS 上 MySQL 服务端口 3306。然后还需要注意的一个配置是,在 Container Station 属性,网络属性中有一个桥接地址,该配置为 Docker 容器提供网络访问,记住这边的网关比如我的是 10.0.3.1

在 NextCloud 容器运行成功之后也可以通过在命令行中使用 docker inspect nextcloud 然后查看 Gateway 地址 docker inspect nextcloud | grep "Gateway" 来查看 Docker 容器的网络配置。

在 Docker 中连接宿主机 MySQL 时需要特别注意,这个时候不能使用 localhost 或者 127.0.0.1,因为这个时候 localhost 或者 127.0.0.1 会指向 Docker 容器本地的地址,需要换成宿主机,比如这里 NAS 的地址,也就是容器的网关地址,比如我这边上面查看得到的 10.0.3.1

填写 NextCloud 配置之前,在 phpMyAdmin 中先创建 nextcloud 用户和 nextcloud 数据库,记住用户名密码,然后在网页中的配置中填写,然后数据库地址一定需要填写 10.0.3.1:3306 ,这边一定要记住使用容器 Gateway 地址。

选择 NextCloud 的一大原因就是因为 NextCloud 的跨平台支持太棒了,所有的平台都有非常好用的客户端。

下面是我的 Mint 上客户端和网页中同步的内容,局域网中速度还是很快的。

nextcloud qnap docker

或者如果熟悉 compose 也可以使用

version: "3"
services:
  nextcloud:
    image: nextcloud:apache
    container_name: nextcloud
    restart: always
    ports:
      - 20080:80
    volumes:
      - /share/NextCloud:/var/www/html

确保 /share/NextCloud 也就是 NextCloud 共享文件夹以及创建

Resilio Sync VS Syncthing

他们都可以免费使用,都是为了解决文件在多台设备之间同步的问题,都采用了 P2P 点对点传输技术(数据不经过第三方,从一点直接加密传输到另一点)。

Resilio Sync

特别的,Resilio Sync 拥有近乎完美的跨平台产品线,Android、iOS、Windows Phone、MacOS、Windows、Linux、BSD、以及几乎所有的商业 NAS 操作系统都有对应的客户端。

从软件界面来说,Resilio Sync 对桌面系统和手机系统都提供了原生的客户端界面,对 Linux、BSD、NAS 等系统则提供基于网页的管理界面。

从原理上来讲 Resilio Sync 是通过官方的 Tracker 追踪服务器建立多台设备之间的连接,最终实现数据从一台设备以最快速度传输到另外一台设备。由于软件本身是闭源的,因此软件在与 Tracker 服务器连接的过程中是否会泄露用户隐私就不得而知了。

Syncthing

有人说,Syncthing 就是为替代 Resilio Sync 而生的,它不但能实现相应的数据同步功能,它还完全开放源代码。

Syncthing 由社区驱动,即程序是由社区里的技术爱好者们共同开发的,任何人都可以参与到软件的开发中去,人人都可以看到软件的源代码。因此,社区负责人敢拍着胸脯说,我们尊重隐私、我们真正安全、我们简单好用。

然而,Syncthing 在跨平台的方面的确略逊一筹,社区仅以开发核心软件为主,如果需要某个特殊系统平台的客户端,要么你自己动手开发,要么就是等其他技术高手开发。比如苹果手机系统 iOS、Windows Phone 就没有对应版本的 Syncthing 客户端。

在软件界面方面,Syncthing 原生仅提供基于终端的命令行控制和基于网页的管理界面。移动端仅提供 Android 系统客户端。近期社区又发布了跨平台的 Syncthing-GTK 客户端支持 Linux 各发行版和 Windows 系统。

如果你想选择这两者,这里有些参考:

  • 如果你需要在多种不同系统的设备之间同步数据,那么就选择 Resilio Sync;
  • 如果你要同步的是机密级别数据,那么就选择 Syncthing;
  • 喜欢折腾就选 Syncthing,闲麻烦就选 Resilio Sync;
  • 如果你想要可靠稳定,未来有意向付费使用更多功能,Resilio Sync 是不二之选;
  • 设备的硬件配置不高的情况下 Syncthing 会更轻便;

2018-06-17 qnap , qnap-tutorial , file-sync , syncthing , dropbox , resilio-sync , resilio , nextcloud

威联通折腾篇四:Container Station 运行 Docker 容器

威联通上有一个 Container Station 的应用,可以直接用官方的 App Center 中下载安装,这其实就是一个 Docker 本地环境,如果熟悉 Docker 使用,那么其实都直接可以 ssh 登录 NAS 然后完全使用命令行来操作。

不过既然威联通提供了一个直观的界面,那么久来使用看看。官方的例子中有一个 GitLab,我的体验来看是非常完美的,几乎就是一键下载部署,即使不了解容器,也不知道 Docker 内部怎么实现,也能够快速的搭建好 GitLab 的服务。威联通 Container Station 中自带很多的服务,比如这个 GitLab,还有 WordPress, MySQL,CentOS, Ubuntu,甚至还有 TensorFlow, Caffe 等等。如果这些还不能满足需求,其实威联通是默认使用的 Docker Hub 的 registry,甚至用户也可以自定义 docker registry,只要能够得到镜像,威联通就能够跑起来,本质上他就是一台虚拟的 Linux 嘛。

使用默认配置创建 GitLab

官方例子,这边不多说了。App 为一群 Docker 镜像文件的集合,目的是提供完整的服务,如 Application+Database,即一个快速的安装包。以 GitLab app 为例,它内含了 GitLab 主程序、PostgreSQL 和 Redis 三个镜像文件。

比如我使用默认的设置创建的 GitLab 服务,在编辑的时候威联通直接展示给我了一个 Docker compose 文件,里面的配置都很详细。

gitlab:
  environment:
    DEBUG: 'false'
    GITLAB_PORT: 10080
    GITLAB_SECRETS_DB_KEY_BASE: qcs-gitlab-app
    GITLAB_SECRETS_OTP_KEY_BASE: qcs-gitlab-app
    GITLAB_SECRETS_SECRET_KEY_BASE: qcs-gitlab-app
    GITLAB_SSH_PORT: 10022
  image: sameersbn/gitlab:10.0.4
  links:
  - redis:redisio
  - postgresql:postgresql
  ports:
  - 10080:80
  - '10022:22'
  restart: always
postgresql:
  environment:
    DB_EXTENSION: pg_trgm
    DB_NAME: gitlabhq_production
    DB_PASS: password
    DB_USER: gitlab
  image: sameersbn/postgresql:9.6-2
  restart: always
redis:
  command:
  - --loglevel warning
  image: sameersbn/redis:latest
  restart: always

GitLab 实在是太占内存了

docker gitlab

使用自定义镜像安装容器

Docker hub 中有无数的应用可供选择,这边以 GitLab 的代替品 Gogs 为例,首先在 Container Station -> 创建 -> 搜索 gogs,选择 Docker Hub 然后从中选择 gogs/gogs 下载镜像。

等待镜像完成之后,创建容器,在高级中选择 NAT 模式,端口映射 10080 和 10022 ,为了不和宿主 NAS 端口产生冲突。然后我习惯创建一个共享文件夹,比如 gogs 来挂载 gogs 的文件内容,以便于快速访问。然后完成创建。

在创建完成,得到 IP 地址之后,点击进入然后开始配置,这边我容器的网关地址是 10.0.3.1,这个地址可以在界面 -> 属性中找到,或者登录 NAS,然后运行 docker inspect container-name | grep "Gateway" 来查看,因为我启用了 NAS 上的 MySQL 服务,所以可以直接可以使用 10.0.3.1:3306 作为数据库地址。然后 Gogs 的其他配置照着填写即可。

完成安装之后对比一下和 GitLab 的内存占用会发现,GitLab 简直就是巨兽。

qnap docker gogs

更多的 Container Station 的使用可以参考下面官方的链接,Docker 真的很好用。

reference


2018-06-17 qnap , qnap-tutorial , container , docker , linux

威联通折腾篇一:使用命令行安装威联通 QNAP 的 qpkg 安装包

如果想要给威联通安装一个 qpkg 的安装包时,最直观界面方式就是在 App Center 中,右上角,将本地的 .qpkg 文件上传到 NAS 并安装。

但是这种方式在外网图形界面加载很慢的情况下是非常难用的,那么这个时候如果能使用命令行安装就非常方便。需要在系统中预先开启 SSH 连接,当然这一步早就做好了。然后使用 ssh 连接登录上。比如下面以安装 Entware 为例

wget http://bin.entware.net/other/Entware_1.00std.qpkg
sh Entware_1.00std.qpkg

经过这两个步骤就 OK 了。使用 opkg 命令可能需要重新登录 NAS SSH。

其他版本的 Entware 可以从这里 获取。

关于什么是 Entware ,可以查看该 wiki,一句话概括 Entware 是一个适用于嵌入式系统的软件包库,使用 opkg 包管理系统进行管理。

软件包列表:

需要注意的是安装 Entware 之后很多命令都存放在 /opt/bin 目录下,需要修改 /root 目录下的 .bashrc 文件中的 PATH 来使这些命令被命令行所见。

export PATH=/opt/bin:$PATH

下面是安装 ng 0.97 版本的日志:

wget http://pkg.entware.net/binaries/x86-64/installer/Entware-ng_0.97.qpkg
--2018-06-15 10:05:57--  http://pkg.entware.net/binaries/x86-64/installer/Entware-ng_0.97.qpkg
Resolving pkg.entware.net (pkg.entware.net)... 81.4.123.217
Connecting to pkg.entware.net (pkg.entware.net)|81.4.123.217|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 25045 (24K) [application/x-gzip]
Saving to: ‘Entware-ng_0.97.qpkg’

Entware-ng_0.97.qpkg                            100%[======================================================================================================>]  24.46K  46.2KB/s    in 0.5s

2018-06-15 10:05:58 (46.2 KB/s) - ‘Entware-ng_0.97.qpkg’ saved [25045/25045]

[~] # sh Entware-ng_0.97.qpkg
Install QNAP package on TS-NAS...
33+1 records in
33+1 records out
24322 bytes (23.8KB) copied, 0.000060 seconds, 386.6MB/s
./
./qinstall.sh
./package_routines
./qpkg.cfg
0+1 records in
0+1 records out
3842 bytes (3.8KB) copied, 0.000018 seconds, 203.6MB/s
3+1 records in
3+1 records out
3842 bytes (3.8KB) copied, 0.001489 seconds, 2.5MB/s
Sym-link /opt ...
Info: Opkg package manager deployment...
Info: Basic packages installation...
Downloading http://pkg.entware.net/binaries/x86-64/Packages.gz.
Updated list of available packages in /opt/var/opkg-lists/packages.
Installing entware-opt (222108-5) to root...
Downloading http://pkg.entware.net/binaries/x86-64/entware-opt_222108-5_x86-64.ipk.
Installing libc (2.23-6) to root...
Downloading http://pkg.entware.net/binaries/x86-64/libc_2.23-6_x86-64.ipk.
Installing libgcc (6.3.0-6) to root...
Downloading http://pkg.entware.net/binaries/x86-64/libgcc_6.3.0-6_x86-64.ipk.
Installing libssp (6.3.0-6) to root...
Downloading http://pkg.entware.net/binaries/x86-64/libssp_6.3.0-6_x86-64.ipk.
Installing librt (2.23-6) to root...
Downloading http://pkg.entware.net/binaries/x86-64/librt_2.23-6_x86-64.ipk.
Installing libpthread (2.23-6) to root...
Downloading http://pkg.entware.net/binaries/x86-64/libpthread_2.23-6_x86-64.ipk.
Installing libstdcpp (6.3.0-6) to root...
Downloading http://pkg.entware.net/binaries/x86-64/libstdcpp_6.3.0-6_x86-64.ipk.
Installing ldconfig (2.23-6) to root...
Downloading http://pkg.entware.net/binaries/x86-64/ldconfig_2.23-6_x86-64.ipk.
Installing findutils (4.6.0-1) to root...
Downloading http://pkg.entware.net/binaries/x86-64/findutils_4.6.0-1_x86-64.ipk.
Installing terminfo (6.0-1c) to root...
Downloading http://pkg.entware.net/binaries/x86-64/terminfo_6.0-1c_x86-64.ipk.
Installing locales (2.23-6) to root...
Downloading http://pkg.entware.net/binaries/x86-64/locales_2.23-6_x86-64.ipk.
Installing opkg (2011-04-08-9c97d5ec-17a) to root...
Downloading http://pkg.entware.net/binaries/x86-64/opkg_2011-04-08-9c97d5ec-17a_x86-64.ipk.
Configuring libgcc.
Configuring libc.
Configuring libssp.
Configuring libpthread.
Configuring librt.
Configuring terminfo.
Configuring ldconfig.
Configuring locales.
Entware uses separate locale-archive file independent from main system
Creating locale archive - /opt/usr/lib/locale/locale-archive
Adding en_EN.UTF-8
Adding ru_RU.UTF-8
You can download locale sources from http://pkg.entware.net/sources/i18n_glib223.tar.gz
You can add new locales to Entware using /opt/bin/localedef.new
Configuring opkg.
Configuring libstdcpp.
Configuring findutils.
Configuring entware-opt.
Updating /opt/etc/ld.so.cache... done.
Link service start/stop script: Entware-ng.sh
Set QPKG information in /etc/config/qpkg.conf
Enable Entware-ng/opkg
[App Center] Entware-ng 0.97 installation succeeded.
[App Center] Entware-ng enabled.

2018-06-15 qnap , qpkg , install , qnap-usage , qnap-tutorial

威联通折腾篇二:使用 frp 内网穿透

这是 QNAP NAS 折腾第二篇,使用 frp 来从外网访问 NAS。威联通自带的 qlink.to 实在是太慢几乎到了无法使用的地步,用 Zerotier 也依然很慢,所以无奈还是用回了 frp.

之前就写过一篇很简单的 frp 使用,不过那是是在 PC 客户端和树莓派上,不过 NAS 就是一个 Linux 嘛,所以也很简单。不过需要注意的是,映射本地 8080 端口,如果需要其他端口,需要相应的添加配置:

[common]
server_addr = frp.server.com          # frp 服务端地址,可以为 IP 或者域名
server_port = 7000                    # 服务端 端口

[ssh-qnap]
type = tcp
local_ip = 127.0.0.1
local_port = 22                       # qnap 22 端口
remote_port = 6022                    # 映射到 6022 端口,这样就可以通过 6022 端口来访问 NAS 22 端口
use_encryption = true
use_compression = true

[qnap-web]
type = tcp
local_ip = 127.0.0.1
local_port = 8080                     # 同理 qnap 8080 管理页面
remote_port = 6080                    # 通过服务端 6080 端口访问 NAS 8080 端口
use_encryption = true
use_compression = true

我现在把所有的 frp 配置放到一个 git 项目中配置,所以一般我也很少更新 frp 的二进制,如果你想要使用最新的 frp 二进制可以到 GitHub 页面


2018-06-15 frp , qnap , qnap-tutorial , qnap-usage , qnap

使用 Zerotier 组建虚拟局域网实现内网穿透

首先 Zerotier 是什么呢? Zerotier 是一拨人为了解决网络复杂,以及因特网过于中心化而提出的解决方案。他们使用点对点 的网络,并且在上面附加一层 VXLAN-like 虚拟网络层 来提高局域网的可见性,安全性。

所以简单来说,Zerotier 通过创建一个虚拟网络,把你的设备添加到这个网络,那么在这个网络内,你的设备就像在同一个路由器内那样可以使用各种端口。

免费版 Zerotier 支持局域网内 100 个设备。Zerotier 支持 Windows、macOS、Linux 三大桌面平台,iOS、Android 两大移动平台,QNAP(威连通)、Synology(群晖)、Western Digital MyCloud NAS(西部数据)三个 NAS 平台,还支持 OpenWrt/LEDE 开源路由器项目。

官网地址:

使用

  • 注册 ZeroTier
  • 创建 Network 私有局域网,得到一个 16 位的 Network ID
  • 在需要加入虚拟局域网的设备上安装各个平台客户端,设备会生成一个 10 位的 ZeroTier address
  • 在设备上加入刚刚创建的 Network ID zerotier-cli join <network id>(或在网页上添加 ZeroTier address)
  • 在官网 network 页面上找到设备,在设备前勾选,信任设备,获得局域网 IP

Windows 系统用命令 IPconfig,Linux/Unix 用命令 ifconfig,然后会看到一个虚拟网卡,有一个 IP 地址。这个 IP 和在官网看到的 network 下的 IP 是一致的,只有同在该虚拟网络下的机器才能访问。

接下来,你可以设置远程桌面(端口号 3389),或者 FTP 服务(端口 21),或者搭建内网网站(端口 80),各种玩法都可以尝试咯。

图文教程可以参考这篇文章

对比

和 ngrok 和 frp 功能类似,但是 ZeroTier 明显入手简单。ZeroTier 只有客户端开源,服务端并没有开源。而 ngrok 和 frp 都是完全开源。但是 ngrok 和 frp 严重依赖于公网固定 IP 的 VPS,是一个中性化的内网穿透工具,一旦中心挂掉,那么所有的节点都无法工作。Zerotier 帮助用户实现了服务端,虽然安全性有待考验,但至少还是能用状态。

另外很多人提到的 N2N 开上去也不错,不过我还没怎么用过。等以后尝试过后再补上。

建立中转服务器 moon

Zerotier 的官方服务器在国外,国内客户端使用时延迟较大,网络高峰期时甚至各个客户端节点之间访问不了。此时,“自定义根服务器”,又称 moon 中转服务器就显得非常重要,它的主要功能是通过自定义的服务器作为跳板加速内网机器之间的互相访问。

Zerotier 定义了几个专业名词:

  • PLANET 行星服务器,Zerotier 各地的根服务器,有日本、新加坡等地
  • moon 卫星级服务器,用户自建的私有根服务器,起到中转加速的作用
  • LEAF 相当于各个枝叶,就是每台连接到该网络的机器节点。

在使用 zerotier-cli listpeers 命令时能看到这几个名词。充当 moon 的机子最好有公网 IP,现在我们尝试用 qnap 搭建一个 moon 中转:

获取 moon.json 文件

zerotier 安装好之后会带有 zerotier-idtool 这个命令,之后的内容需要依赖该命令。假设现在有一台公网固定 IP 的 VPS,在上面安装完 Zerotier 之后。

cd /var/lib/zerotier-one
zerotier-idtool initmoon identity.public > moon.json

获得 moon.json 文件。查看文件内容,其中 id 为 VPS 的 Zerotier ID。 vi 编辑 moon.json,修改 “stableEndpoints” 为 VPS 的公网的 IP,以 IPv4 为例:

"stableEndpoints": [ "8.8.8.8/9993" ]

8.8.8.8 为公网 IP,9993 为 Zerotier 默认端口。

另外,记录下 json 中的 id 值,是一个 10 位的字符串。

生成签名文件

用到上一步中的 moon.json, 执行

zerotier-idtool genmoon moon.json

执行之后生成 000000xxxx.moon 文件。

将 moon 节点加入网络

在 VPS 的 Zerotier 安装目录下(/var/lib/zerotier-one)建立文件夹 moons.d,将生成的 .moon 文件拷贝进去。

重启 zerotier,重启电脑。至此,VPS 上(moon 服务器)配置完成。

其他客户端机器连接 moon 节点

其他虚拟局域网中的机器想要连接到 moon 节点的话有两种方法,第一种方法就是使用 zerotier-cli orbit 命令。连接 moon 节点方法一,使用之前步骤中 moon.json 文件中的 id 值 (10 位的字符串)

分别在客户端机器里执行:

zerotier-cli orbit <id> <id>

完成

第二种方法是需要在 /var/lib/zerotier-one 目录下新建 moons.d 文件夹和 moon 节点一样,将 000000xxxx.moon 文件放到其中,并重启 zerotier。

测试

zerotier-cli listpeers

如果有 moon 服务器 IP 地址的那一行后面有 moon 字样,证明 moon 节点已经被本机连接。

不同系统下的 ZeroTier 目录位置:

  • Windows: C:\ProgramData\ZeroTier\One
  • Macintosh: /Library/Application\ Support/ZeroTier/One)
  • Linux: /var/lib/zerotier-one
  • FreeBSD/OpenBSD: /var/db/zerotier-one

2018-06-14 zerotier , linux , nas , network , virtual-networks

Celery 又一坑:时区错误

Celery 使用过程中又遇一坑,最近升级项目中使用的 Celery 到 4.1.1,突然发现一些定时任务突然不执行了。开始还以为代码哪里做了变化,尝试找了很久,然后打开 scheduler 的日志观察了一段时间。

Celery config 中的配置是如下所示,理论上,早间的任务应该在 8 点到 12 点 每隔 5 分钟执行一次,然后午间和晚间的以此类推。

app.conf.timezone = 'Asia/Shanghai'

app.conf.beat_schedule = {
    'morning': {
        'task': 'worker.xxx.get_xxx',
        'schedule': crontab(minute='*/5', hour='8-12'),
        'args': ('早间',),
        'options': {
            'queue': 'xxx'
        }
    },
    'afternoon': {
        'task': 'worker.xxx.get_xxx',
        'schedule': crontab(minute='*/5', hour='12-18'),
        'args': ('午间',),
        'options': {
            'queue': 'xxx'
        }
    },
    'evening': {
        'task': 'worker.xxx.get_xxx',
        'schedule': crontab(minute='*/5', hour='19-21'),
        'args': ('晚间',),
        'options': {
            'queue': 'xxx'
        }
    },
}

但是观察日志发现,即使现在是下午 4 点,但是上午的任务依然在跑,这个时候突然想起来,是不是因为版本升级导致,果不然,一查 GitHub 就有人反馈这个问题,目前解决方法很简单,为了恢复可用状态,将 celery 回滚到了 4.0.2 版本。暂时没有发现问题。

看 issue 已经意识到该问题,希望能在 4.2 版本中修复吧,有时间的话我再看看他的源码。


2018-06-13 celery , python , linux , message , queue , bug

使用 lombok 简化 Java 代码

lombok 在编译器编译时通过操作 AST(抽象语法树)改变字节码生成。也就是说他可以改变 Java 语法。lombok 不像 Spring 的依赖注入是运行时的特性,而是编译时的特性。使用 lombok 需要对应 IDE 插件配合,具体可参考官网。

安装配置

官网地址:https://projectlombok.org/

添加 maven

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.20</version>
</dependency>

最新的版本号,可以在官网或者 mvnrepository 找到。 如果使用 Intellij IDEA 还需要安装一个插件。

使用

Data 注解

类注解

import lombok.Data;

@Data
public class Thing {
    private Long id;
    private String desc;
}

通过添加注解 @Data 可以给类快速添加 getset 方法,toString() 方法等等。 @Data 注解其实是 @ToString@Getter@SetterRequiredArgsConstructor@EqualsAndHashCode 注解的缩写。

其实等效于

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@ToString
@RequiredArgsConstructor
@EqualsAndHashCode
public class Thing {
    @Setter @Getter private Long id;
    @Setter @Getter private String desc;
}

相关的注解:

  • @Getter/@Setter:用在属性上,再也不用自己手写 setter 和 getter 方法了,还可以指定访问范围
  • @ToString:用在类上,可以自动覆写 toString 方法,当然还可以加其他参数,例如 @ToString(exclude=”id”) 排除 id 属性,或者 @ToString(callSuper=true, includeFieldNames=true) 调用父类的 toString 方法,包含所有属性
  • @EqualsAndHashCode:用在类上,自动生成 equals 方法和 hashCode 方法
  • @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor:用在类上,自动生成无参构造和使用所有参数的构造函数以及把所有 @NonNull 属性作为参数的构造函数,如果指定 staticName = “of”参数,同时还会生成一个返回类对象的静态工厂方法,比使用构造函数方便很多
  • @Data:注解在类上,相当于同时使用了@ToString@EqualsAndHashCode@Getter@Setter@RequiredArgsConstrutor这些注解,对于 POJO 类十分有用
  • @Value:用在类上,是 @Data 的不可变形式,相当于为属性添加 final 声明,只提供 getter 方法,而不提供 setter 方法
  • @NonNull 用在方法参数上,该变量不能为空,否则就抛出异常
  • @Builder:用在类、构造器、方法上,为你提供复杂的 builder APIs,让你可以像如下方式一样调用 Person.builder().name(“Adam Savage”).city(“San Francisco”).job(“Mythbusters”).job(“Unchained Reaction”).build(); 更多说明参考 Builder
  • @SneakyThrows:自动抛受检异常,而无需显式在方法上使用 throws 语句
  • @Synchronized:用在方法上,将方法声明为同步的,并自动加锁,而锁对象是一个私有的属性 $lock 或 $LOCK,而 java 中的 synchronized 关键字锁对象是 this,锁在 this 或者自己的类对象上存在副作用,就是你不能阻止非受控代码去锁 this 或者类对象,这可能会导致竞争条件或者其它线程错误
  • @Getter(lazy=true):可以替代经典的 Double Check Lock 样板代码
  • @Log:根据不同的注解生成不同类型的 log 对象,但是实例名称都是 log,有六种可选实现类

    @CommonsLog Creates log = org.apache.commons.logging.LogFactory.getLog(LogExample.class); @Log Creates log = java.util.logging.Logger.getLogger(LogExample.class.getName()); @Log4j Creates log = org.apache.log4j.Logger.getLogger(LogExample.class); @Log4j2 Creates log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class); @Slf4j Creates log = org.slf4j.LoggerFactory.getLogger(LogExample.class); @XSlf4j Creates log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

ToString 注解

Slf4j 注解

正如上面所例举,lombok 可以使用的日志框架有很多,拿最常见的 @Slf4j 来举例

@Slf4j
public class A {
    public A() {
        log.info("I'm sectionVO : {}", toString());
    }
}

编译会自动生成

private static final Logger log = LoggerFactory.getLogger(A.class);

Builder 注解

如果在类上使用 @Builder 注解,则会给该类直接生成 builder 模式,然后可以使用 builder() 方法返回的 builder 来构造类。

如果要对 Builder 中的值赋予默认值,有两种方式,比如对于

@Builder
public class Person {
  private String firstname = "John";
  private String lastname = "Doe";
}

第一种方式就是手动编写一个静态内部类

@Builder
public class Person {
  private String firstname;
  private String lastname;
  private String middleName;

  public static class PersonBuilder {
    private String firstname = "John";
    private String lastname = "Doe";
  }
}

或者在 v1.16.16 之后添加的新功能

@Builder
public class Person {
  @Builder.Default private String firstname = "John";
  @Builder.Default private String lastname = "Doe";
  private String middleName;
}

当一个类被标注 @Builder 后会自动产生下面 7 件事情:

  • 一个内部静态类 FooBuilder ,类内部有着和类相同类型的内部变量
  • builder 内部:One private non-static non-final field for each parameter of the target
  • builder 内部:package private no-args empty constructor
  • builder 内部:A ‘setter’-like method for each parameter of the target: It has the same type as that parameter and the same name. It returns the builder itself, so that the setter calls can be chained, as in the above example.
  • builder 内部:A build() method which calls the method, passing in each field. It returns the same type that the target returns.
  • builder 内部:A sensible toString() implementation.
  • builder 内部:A builder() method, which creates a new instance of the builder.

最后,如果在类上注解 @AllArgsConstructor(access = AccessLevel.PACKAGE) 那么可以将 @Builder 应用到类上。如果自己显示定义了构造函数,那么将 @Builder 用在该构造方法上。

总结 Lombok 实践

  • Lombok 注解的内容不要参杂任何逻辑
  • 在 DAOs 上使用 @Data
  • 对不可变对象使用 @Value
  • 当类有很多相同类型成员变量,使用 @Builder
  • 慎用其他不常用注解,比如 @Cleanup,@SneakyThrows,@Synchronized 等

其他的特性可以在这里看到:https://projectlombok.org/features/all

reference


2018-06-11 lombok , java , annotation

电子书

最近文章

  • Linux 下使用 emoji Ubuntu 或者其他一些 Linux 发行版会内置 Google Noto Color emoji font
  • 理解 GraphQL Schema 结构定义 在上一篇 GraphQL 使用 中了解了 GraphQL 大致用法,如果要更加深入的了解 GraphQL ,那就不得不重新从 Schema 来认识 GraphQL,说到底 GraphQL 还是一个强类型定义,客户端可操作的类型都是需要提前定义好的,这个结构就是这篇文章的重点 Schema.
  • 从 MySQL 迁移到 PostgreSQL 方案调研 之前的文章 PostgreSQL 初识 和 PostgreSQL 数据类型 大致的把 PostgreSQL 了解了一下,那么接下来就是真正地把它用起来。
  • GraphQL 使用 很多人都知道 GraphQL 起源于 Facebook,但是似乎很少中文材料提到 GraphQL 出现的契机,我在看完这个纪录片 之后才对 GraphQL 的出现有更加深刻的了解。都知道当年 Facebook 的移动客户端都是网页,随着移动互联网发展,Facebook 网页实现的客户端性能和体验受到非常严重的影响,所以后来不得不去做原生的应用。那么这个时候就遇到了一个问题,原来直接使用网页,那么不同客户端用的接口都是给网页用的,最多做一下屏幕的适配,但是如果使用原生的应用,那么必然会需要设计不同的 API,而 Facebook 的工程师发现,对于复杂的 Feed 流,评论等等,用 RESTful 接口将是一个灾难,所以一帮人开始设计一种查询语言,这就是后来的 GraphQL。也应该纠正一下 Facebook 那帮工程师,只是开源了一份设计和一份实现,但他们万万没有想到开源社区的力量,就像片中 Nick Schrock 说的那样,他低估了社区的力量,在短短的几个月,几年时间中,GraphQL 就已经有了非常多语言的支持,周边应用也非常丰富。原来在脑海里的想法,都没有到生产环境中用过,就这样在所有社区的人的努力下成为了改变这个行业的一部分。
  • Drools : Guided Decision Table Column