标签 Python 下的文章

Hello,Termux

程序员或多或少都有一颗Geek(极客)的心^0^。- Tony Bai

折腾开始。

这一切都源于前不久将手机换成了Xiaomi的MIX2。因为青睐开放的系统(相对于水果公司系统的封闭,当然Mac笔记本除外^0^),我长期使用Android平台的手机。但之前被三星Note3手机的“大屏”搞的不是很舒服,这两年一直用5寸及以下的手机,因为单手操作体验良好。MIX2的所谓“全面屏”概念又让我回归到了大屏时代。

除了大屏,现在手机“豪华”的硬件配置也让人惊叹:高通骁龙835,8核,最高主频 2.45GHz;6GB以上的LPDDR4x的双通道大内存,怪不得微软和高通都开始合作生产基于高通ARM处理器的Win10笔记本了,这配置支撑在笔记本上办公+浏览网页绰绰有余。不过对于不怎么玩游戏的我而言,这种配置仅仅用作手机日常功能有些浪费。于是有了“mobile coding”的想法和需求,至少现在是这样想的,冲动也好,伪需求也好,先实现了再说。

一、神器Termux,不仅仅是一个terminal emulator

所谓”mobile coding”不仅仅是要通过手机ssh到服务器端进行coding,还要支持在手机上搭建一个dev环境。dev环境这个需求是以往我安装的ConnectBot等ssh client端工具所无法提供的,而其他一些terminal工具,诸如Terminal Emulator for Android仅仅提供一些shell命令的支持,适合于那些喜爱使用命令行对Android机器进行管理的”administrator”们,但对dev环境的搭建支持有限的。于是神器Termux登场了。

Termux是什么?Termux首先是一个Android terminal emulator,可以像那些terminal工具一样,提供基本的shell操作命令;除此之外更为重要的是它不仅仅是一个terminal emulator。Termux提供了一套模拟的Linux环境,你可以在无需root、无需root、无需root的情况下,像在PC linux环境下一样进行各种Linux操作,包括使用apt工具进行安装包管理、定制shell、访问网络、编写源码、编译和运行程序,甚至将手机作为反向代理、负载均衡服务器或是Web服务器,又或是做一些羞羞的hack行为等。

1、安装

Termux仅支持Android 5.0及以上版本(估计现在绝大多数android机都满足这一条件)。在国内建议使用F-Droid安装Termux(先下载安装F-Droid,再在F-Droid内部搜索Termux,然后点击安装),国内的各种安装助手很少有对这个工具的支持。或是到apk4fun下载Termux的apk包(size非常小)到手机中安装(安装时需要连接着网络)。当前Termux的最新版本为0.54

在桌面点击安装后的Termux图标,我们就启动了一个Termux应用,见下图:

img{512x368}

2、Termux初始环境探索

Mix2手机的Android系统使用的是Android 7.1.1版本,桌面Launcher用的是MIUI 9.1稳定版,默认的shell是bash。通过Termux,我们可以查看Android 7.1.1.使用的Linux内核版本如下:

$uname -a
Linux localhost 4.4.21-perf-g6a9ee37d-06186-g2b2a77b #1 SMP PREEMPT Thu Oct 26 14:55:45 CST 2017 aarch64 Android

可以看出Linux内核是4.4.21,采用的CPU arch family是ARM aarch64

我再来看一下Termux提供的常见目录结构:

Home路径:

$cd ~/
$pwd
/data/data/com.termux/files/home

//或者通过环境变量HOME获取:

$echo $HOME
/data/data/com.termux/files/home

长期使用Linux的朋友可能会发现,这个HOME路径好是奇怪,一般的标准Linux发行版,比如Ubuntu都是在”/home”下放置用户目录,但termux环境中HOME路径却是一个奇怪的位置。在Termux官方Wiki中,我们得到的答案是:Termux是一个prefixed system。

这个prefix的含义我理解颇有些类似于我们在使用configure脚本时指定的–prefix参数的含义。我们在执行configure脚本时,如果不显式地给–prefix传入值,那么make install后,包将被install在标准位置;否则将被install在–prefix值所指定的位置。

prefixed system意味着Termux中所有binaries、libraries、configs都不是放在标准的位置,比如:/usr/bin、/bin、/usr/lib、/etc等下面。Termux expose了一个特殊的环境变量:PREFIX(类似于configure –prefix参数选项):

$echo $PREFIX
/data/data/com.termux/files/usr

$cd $PREFIX
$ls -F
bin/  etc/  include/  lib/  libexec/  share/  tmp/  var/

是不是有些似曾相识?但Termux的$PREFIX路径与标准linux的根路径下的目录结构毕竟还存在差别,但有着对应关系,这种对应关系大致是:

Termux的$PREFIX/bin  <=>  标准Linux环境的 /bin和/usr/bin
Termux的$PREFIX/lib  <=>  标准Linux环境的 /lib和/usr/lib
Termux的$PREFIX/var  <=>  标准Linux环境的 /var
Termux的$PREFIX/etc  <=>  标准Linux环境的 /etc

因此,基本可以认为Termux的$PREFIX/就对应于标准Linux的/路径。

3、更新源和包管理

Termux的牛逼之处在于它基于debian的APT包管理工具进行软件包的安装、管理和卸载,就像我们在Ubuntu下所做的那样,非常方便。

Termux自己维护了一个源,提供各种专门为termux定制的包:

# The main termux repository:
#deb [arch=all,aarch64] http://termux.net stable main

同时,termux-packages项目为开发者和爱好者提供了构建工具和脚本,通过这些工具和脚本,我们可以将自己需要的软件包编译为可以在termux运行的版本,并补充到Termux的源之中。我大致测试了一下官方这个源还是可用的,虽然初始连接的响应很缓慢。

国内清华大学维护了一个Termux的镜像源,你可以通过编辑 /data/data/com.termux/files/usr/etc/apt/sources.list文件或执行apt edit-sources命令编辑源(在Shell配置中添加export EDITOR=vi后,apt edit-sources才能启动编辑器进行编辑):

# The main termux repository:
#deb [arch=all,aarch64] http://termux.net stable main
deb [arch=all,aarch64] http://mirrors.tuna.tsinghua.edu.cn/termux stable main

剩下的操作与Ubuntu上的一模一样,无非apt update后,利用apt install安装你想要的包。目前Termux源中都有哪些包呢?可以通过apt list命令查看:

$apt list
Listing... Done
aapt/stable 7.1.2.33-1 aarch64
abduco/stable 0.6 aarch64
abook/stable 0.6.0pre2-1 aarch64
ack-grep/stable 2.18 all
alpine/stable 2.21 aarch64
angband/stable 4.1.0 aarch64
apache2/stable 2.4.29 aarch64
apache2-dev/stable 2.4.29 aarch64
apksigner/stable 0.4 all
apr/stable 1.6.3 aarch64
apr-dev/stable 1.6.3 aarch64
apr-util/stable 1.6.1 aarch64
apr-util-dev/stable 1.6.1 aarch64
apt/stable,now 1.2.12-3 aarch64 [installed]
apt-transport-https/stable 1.2.12-3 aarch64
... ...
zile/stable 2.4.14 aarch64
zip/stable 3.0-1 aarch64
zsh/stable,now 5.4.2-1 aarch64 [installed]

查看是否有需要更新的包列表:

$apt list --upgradable

以安装golang为例:

$apt install golang
....
$go version
go version go1.9.2 android/arm64

img{512x368}

Termux源中的包似乎更新的很勤奋,Go 1.9.2才发布没多久,这里已经是最新版本了,这点值得赞一个!

二、开发环境搭建

我的目标是mobile coding,需要在Termux上搭建一个dev环境,以Go环境为例。

1、sshd

在搭建和配置阶段,如果直接通过Android上的软键盘操作,即便屏再大,那个体验也是较差的。我们最好通过PC连到termux上去安装和配置,这就需要我们在Termux上搭建一个sshd server。下面是步骤:

$apt install openssh
$sshd

就这么简单,一个sshd的server就在termux的后台启动起来了。由于Termux没有root权限,无法listen数值小于1024的端口,因此termux上sshd默认的listen端口是8022。另外termux上的sshd server不支持用户名+密码的方式进行登录,只能用免密登录的方式,即将PC上的~/.ssh/id_rsa.pub写入termux上的~/.ssh/authorized_keys文件中。关于免密登录的证书生成方法和导入方式,网上资料已经汗牛充栋,这里就不赘述了。导入PC端的id_rsa.pub后,PC就可以通过下面命令登录termux了:

$ssh 10.88.46.79  -p 8022
Welcome to Termux!

Wiki:            https://wiki.termux.com
Community forum: https://termux.com/community
IRC channel:     #termux on freenode
Gitter chat:     https://gitter.im/termux/termux
Mailing list:    termux+subscribe@groups.io

Search packages:   pkg search <query>
Install a package: pkg install <package>
Upgrade packages:  pkg upgrade
Learn more:        pkg help

其中10.88.46.79是手机的wlan0网卡的IP地址,可以在termux中使用ip addr命令获得:

$ip addr show wlan0
34: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 3000
    ... ...
    inet 10.88.46.79/20 brd 10.88.47.255 scope global wlan0
       valid_lft forever preferred_lft forever
    ... ...

2、定制shell

Termux支持多种主流Shell,默认的Shell是Bash。很多开发者喜欢zsh + oh-my-zsh的组合,Termux也是支持的,安装起来也是非常简单的:

$ apt install git
$ apt install zsh
$ git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh
$ cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc
$ chsh zsh

与在PC上安装和配置zsh和oh-my-zsh没什么两样,你完全可以按照你在PC上的风格定制zsh的Theme等,我用的就是默认theme,所以也无需做太多变化,顶多定制一下PROMPT(~/.oh-my-zsh/themes/robbyrussell.zsh-theme中的PROMPT变量)的格式^0^。

3、安装vim-go

在terminal内进行Go开发,vim-go是必备之神器。vim-go以及相关自动补齐、snippet插件安装在不同平台上都是大同小异的,之前写过两篇《Golang开发环境搭建-Vim篇》和《vim-go更新小记》,大家可以参考。

不过这里有一个较为关键的问题,那就是Termux官方源中的vim 8.0缺少了对python和lua的支持:

 $vim --version|grep py
+cryptv          +linebreak       -python          +viminfo
+cscope          +lispindent      -python3         +vreplace
$vim --version|grep lua
+dialog_con      -lua             +rightleft       +windows

而一些插件又恰需要这些内置的支持,比如ultisnips需要vim自带py支持;neocomplete又依赖vim的lua支持。这样如果你还想要补齐和snippet特性,你就需要在Termux下面自己编译Vim的源码了(configure时加上对python和lua的支持)。

4、中文支持

无论是PC还是Termux使用的都是UTF8的内码格式,但是在安装完vim-go后,我试着用vim编辑一些简单的源码,发现在vim中输入的中文都是乱码。这里通过一个配置解决了该问题:

//~/.vimrc

添加一行:

set enc=utf8

至于其中的原理,可以参见我N年前写的《也谈VIM字符集编码设置》一文。

三、键盘适配

现阶段,写代码还是需要键盘输入的(憧憬未来^0^)。

1、软键盘

使用原生自带的默认软键盘在terminal中用vim进行coding,那得多执着啊,尤其是在vim大量使用ESC键的情况下(我都没找到原生键盘中ESC键在哪里:()。不过Termux倒是很具包容心,为原生软键盘提供了扩展支持:用两个上下音量键协助你输入一些原生键盘上没有或者难于输入的符号,比如(全部的模拟按键列表参见这里):

清理屏幕:用volume down + L 来模拟 ctrl + L
结束前台程序:用volume down + C 来模拟 ctrl + C
ESC:用volume up + E 来模拟
F1-F9: 用volume up + 1 ~ 9 来模拟

据网友提示:volume up + Q键可以打开扩展键盘键,包括ESC、CTRL、ALT等,感谢。

这样仅能满足临时的需要,要想更有效率的输入,我们需要Hacker’s Keyboard。顾名思义,Hacker’s Keyboard可以理解为专为Coding(无论出于何种目的)的人准备的。和Termux一样,你可以从F-droid安装该工具。启动该app后,app界面上有明确的使用说明,如果依旧不明确,还可以查看这篇图文并茂的文章:《How to Use Hacker’s Keyboard》。默认情况下,横屏时Hacker’s keyboard会使用”Full 5-row layout”,即全键盘,竖屏时,则是4-row layout。你可以通过“系统设置”中的“语言和输入法”配置中对其进行设置,让Hacker’s keyboard无论在横屏还是竖屏都采用全键盘(我们屏幕够大^0^):

img{512x368}
横屏

img{512x368}
竖屏

Hacker’s Keyboard无法支持中文输入,这点是目前的缺憾,不过我个人写代码时绝少使用中文,该问题忽略不计。

2、外接蓝牙键盘

Hacker’s Keyboard虽然一定程度提升了Coding时的输入效率,但也仅是权宜之计,长时间大规模通过软键盘输入依旧不甚可取,外接键盘是必须的。对于手机而言,目前最好的外接连接方式就是蓝牙。蓝牙键盘市面上现在有很多种,我选择了老牌大厂logitechK480。这款键盘缺点是便携性差点、按键有些硬,但按键大小适中;而那些超便携的蓝牙键盘普遍键帽太小,长时间Coding的体验是个问题。

img{512x368}

Termux对外接键盘的支持也是很好的,除了常规输入,通过键盘组合键Ctrl+Alt与其他字母的组合实现各种控制功能,比如:

ctrl + alt + c => 实现创建一个新的session;
ctrl + alt + 上箭头/下箭头 => 实现切换到上一个/下一个session的窗口;
ctrl + alt + f => 全屏
ctrl + alt +v => 粘贴
ctrl + alt + +/- => 实现窗口字体的放大/缩小

不过,外接键盘和Hacker’s keyboard有一个相同的问题,那就是针对Termux无法输入中文。我尝试了百度、搜狗等输入法,无论如何切换(正常在其他应用中,通过【shift + 空格】实现中英文切换)均只是输入英文。

四、存储

到目前为止,我们提到的路径都在termux的私有的内部存储(private internal storage)路径下,这类存储的特点是termux应用内部的、私有的,一旦termux被卸载,这些数据也将不复存在。Android下还有另外两种存储类型:shared internal storage和external storage。所谓shared internal storage是手机上所有App可以共享的存储空间,放在这个空间内的数据不会因为App被卸载掉而被删除掉;而外部存储(external storage)主要是指外部插入的SD Card的存储空间。

默认情况下,Termux只支持private internal storage,意味着你要做好数据备份,否则一旦误卸载termux,数据可就都丢失了;数据可以用git进行管理,并sync到云端。

Termux提供了一个名为termux-setup-storage的工具,可以让你在Termux下访问和使用shared internal storage和external storage;该工具是termux-tools的一部分,你可以通过apt install termux-tools来安装这些工具。

执行termux-setup-storage(注意:这个命令只能在手机上执行才能弹出授权对话框,通过远程ssh登录后执行没有任何效果)时,手机会弹出一个对话框,让你确认授权:

img{512x368}

一旦授权,termux-setup-storage就会在HOME目录下建立一个storage目录,该目录下的结构如下:

➜  /data/data/com.termux/files/home $tree storage
storage
├── dcim -> /storage/emulated/0/DCIM
├── downloads -> /storage/emulated/0/Download
├── movies -> /storage/emulated/0/Movies
├── music -> /storage/emulated/0/Music
├── pictures -> /storage/emulated/0/Pictures
└── shared -> /storage/emulated/0

6 directories, 0 files

我们看到在我的termux下,termux-setup-storage在storage下建立了6个符号链接,其中shared指向shared internal storage的根目录,即/storage/emulated/0;其余几个分别指向shared下的若干功能目录,比如:相册、音乐、电影、下载等。我的手机没有插SD卡,可能也不支持(市面上大多数手机都已经不支持了),如果插了一张SD卡,那么termux-setup-storage还会在storage目录下j建立一个符号链接指向在external storage上的一个termux private folder。

现在你就可以把数据放在shared internal storage和external storage上了,当然你也可以在Termux下自由访问shared internal storage上的数据了。

五、小结

Termux还设计了支持扩展的Addon机制,支持通过各种Addon来丰富Termux功能,提升其能力,这些算是高级功能,在这篇入门文章里就先不提及了。好了,接下来我就可以开始我的mobile coding了,充分利用碎片时间。后续在使用Termux+k480的过程中如果遇到什么具体的问题,我再来做针对性的解析。


微博:@tonybai_cn
微信公众号:iamtonybai
github.com: https://github.com/bigwhite

源创会开源访谈:十年成长,Go语言的演化之路

在参加源创会沈阳站分享之前,接受了开源中国社区编辑王练的文字专访,以下是我针对专访稿的内容。

同时该专访稿首发于开源中国开源访谈栏目,大家可以点击这里看到首发原稿。

1、首先请介绍一下自己

大家好!我叫白明(Tony Bai),目前是东软云科技的一名架构师,专职于服务端开发,日常工作主要使用Go语言。我算是国内较早接触Go语言的程序员兼Advocater了,平时在我的博客微博和微信公众号”iamtonybai”上经常发表一些关于Go语言的文章和Go生态圈内的信息。

在接触Go之前,我主要使用C语言开发电信领域的一些后端服务系统,拥有多年的电信领域产品研发和技术管理经验。我个人比较喜换钻研和分享技术,是《七周七语言》一书的译者之一,并且坚持写技术博客十余年。同时我也算是一个开源爱好者,也在github上分享过自己开发的几个小工具。

目前的主要研究和关注的领域包括:Go、KubernetesDocker区块链和儿童编程教育等。

img{512x368}

2、最初是因为什么接触和使用 Go 语言的?它哪方面的特性吸引了您?

个人赶脚:选编程语言和谈恋爱有些像(虽然我只谈过一次^_^),我个人倾向一见钟情。我个人用的最多的编程语言是GoC,这两门语言算是我在不同时期的“一见钟情”的对象吧,也是最终“领(使)证(用)”的,前提:编程世界是“一夫多妻制”^0^。

当然早期也深入过C++,后来JavaRubyCommon LispHaskellPython均有涉猎,这些语言算是恋爱对象,但最终都分手了。

最初接触到Go应该是2011年,那是因为看了Rob Pike的3 Day Go Course,那时Go 1.0版本还没有发布,如果没记错,Rob Pike slide中用的还是Go r60版本的语法。现在大脑中留存的当时的第一感觉就是“一见钟情”!

现在回想起来,大致有这么几点原因:

  • Go与C一脉相承,对于出身C程序员的我来说,这一语言传承非常自然,多体现在语法上;
  • Go语言非常简单,尤其是GC、并发goroutine、interface,让我眼前一亮;
  • Rob Pike的Go Course Slide组织的非常好,看完三篇Slide,基本就入门了。

于是在那之后,又系统阅读了Ivo Balbaert的《The Way To Go》、《Programming in Go – Creating Applications for the 21st Century》等基本新鲜出炉的书,于是就走入了Go语言世界。

不过当时Go1尚未发布,Go自身也有较大变化,工作中也无法引入这门语言,2013年对Go的关注有些中断,2014年又恢复,直至今天。现在感觉到:如果工作语言与兴趣语言能保持一致是多么幸福的一件事啊。

3、有人说 Go 是互联网时代的 C 语言,对于这两门语言,您是怎么看的?

如果没记错,至少在国内,第一个提出这种观点的是现七牛的ceo许式伟了,老许是国内第一的Go 鼓吹者,名副其实;而且许式伟的鼓吹不仅停留在嘴上,更是付诸于实践:据说其七牛云的基础设施基本都是Go开发的。因此,对他的“远见卓识”还是钦佩之至的。

C语言缔造的软件行业的成就是举世瞩目,也是公认的。其作者Dennis Ritchie授予图灵奖就是对C语言最大的肯定和褒奖。C语言缔造了单机操作系统和基础软件的时代:UnixLinux、nginx/apache以及无数以*inx世界为中心的工具,是云时代之前最伟大的系统编程语言和基础设施语言。

至于 “Go是互联网时代的 C 语言”这一观点,如果在几年前很多人还会疑惑甚至不懈,但现在来看:事实胜于雄辩。我们来看看当前CNCF基金会(Cloud Native Computing Foundation)管理的项目中,有一大半都是Go语言开发的,包括KubernetesPrometheus等炙手可热的项目;这还不包括近两年最火的docker项目。事实证明:Go已成为互联网时代、云时代基础设施领域、云服务领域的最具竞争力的编程语言之一。

不过和C不同的是,Go语言还在发展,还在演进,还有巨大的提升空间,Gopher群体还在变大,去年再次成为Tiboe的年度语言就是例证。

当然我们还得辩证的看,Go语言虽然在云时代基础设施领域逐渐继承C语言的衣钵,但是由于语言设计理念和设计哲学上的原因,在操作系统以及嵌入式领域,Go还在努力提升。

4、Go 也经常被拿来和 Java、Rust 等语言比较,您认为它最适合的使用场景有哪些?

早期对Java有所涉猎,但止步于Java体量过重和框架过多;Rust和Go一样是近几年才兴起的一门很有理想、很有抱负的编程语言,其目标就是安全的系统级编程语言,运行性能极佳,用以替代C/C++的,但就像前面所提到的那样,第一眼看到Rust的语法,就没有那种“一见钟情”的赶脚,希望Rust不要像C++那样,演变的那么复杂。

Go从其第一封设计email出炉到如今已有十年了,我觉得也不应该由我来告诉大家Go更适合应用在什么领域了,事实摆在那里:“大家都用的地方,总是对的”。这里我只是大致归纳一下:

Go在数据科学、人工智能领域也有较大进展,希望在将来能看到Go在这些领域有杀手级项目出现。

5、Go发展已有10 年,其特性随着版本的迭代不断在更新,您觉得它最好的和最需要改进的特性分别有哪些?

每种语言都有自己的设计哲学和设计者的考量。我在GopherChina 2017的topic中就提到过Go语言的价值观,其中之一就是Simplicity,即简单。相信简单也是让很多开发者走进Gopher世界的重要原因。从今年GopherCon 2017大会上Russ Cox的“Toward Go 2”的主题演讲中,我们也可以看出:Go team并不会单纯地为了迎合community的意愿去堆砌feature,那go势必走上c++的老路,变得日益复杂,Go受欢迎的基础之一就不存在了。

但演进就一定会要付出代价的,尤其是Go1的约束在前。从我个人对Go的应用来看,最想看到的是包管理和error处理方面的体验提升。但我觉得这两点都是可以通过渐进改进实现的,甚至不会影响到Go1兼容性,不会像引入generics机制,实现难度也不会太高。

对于目前的error handling机制,我个人并没有太多的排斥,这可能是因为我出身C程序员的缘故吧。在error handling这块,只是希望能让gopher拥有更好的体验即可,比如说围绕现有的error机制,增加一些设施以帮助gopher更好的获取error cause信息,就像github.com/pkg/errors包那样。

对于社区呼声很高的generics(泛型),我个人倒是没有什么急切需求。generics虽然可以让大幅提升语言的表现力(expressiveness),但也给语言自身带来了较大的复杂性。就个人感受而言,C++就是在加入generics后才变得无比庞大和复杂的,同时generics还让很多C++ programmer沉溺于很多magic trick中无法自拔,这对于以“合作分工”为主流的软件开发过程来说,并不是好事情。

6、Go 官方团队已发布 2.0 计划,更侧重于兼容性和规模化方面。对此,您怎么理解?Go 否已达到最佳性能?

这个问题和上面的问题有些类似,我的想法差不多。Go team在特性演进方面会十分谨慎,这也是go Team一贯的风格。从Go1到Go2,从现在看来,这个时间跨度不会很短,也许是2-3年也不一定,心急吃不了热豆腐^0^,社区分裂可不是go team想看到的事情,python可是前车之鉴。

另外,Go性能显然还是有改善空间的,尤其是编译性能、GC吞吐和延迟的tradeoff方面;另外goroutine调度器算法方面可能还有改进空间。当前Goroutine调度算法的实现者Dmitry Vyukov之前就编写了一个scheduler优化的proposal: NUMA-aware scheduler for Go(针对numa体系的优化),但也许因为重要性、优先级等考量,一直没有实现,也许后续会实现。

7、Go 在国内似乎比国外还要火,您认为造成这种现象的原因是什么?

从一些搜索引擎的trend数据来看,Go在中国地区的确十分火热,甚至在热度值上是领先于欧美世界的。个人觉得造成这种现象的原因可能有如下几点:

  • 语言本身的接受度高

首先,从Go语言本身考虑。事实证明了:Go语言的设计匹配了国内程序员的行业业务需求和对语言特性的需求(口味):
a) 语言:简单、正交组合和并发;开发效率和运行效率双高;
b) 自带battery:丰富的标准库和高质量第三方库;
c) 迎合架构趋势:天生适合微服务….

  • 引入早且与Go advocator的努力分不开

当前再也不是那个“酒香不怕巷子深”的年代了,再好的编程语言也需要推广和宣称。Go team在社区建设、全世界推广方面也是不遗余力。至于国内更是有像许式伟、Astaxie这样的占据高端IT圈子的advocator在站台宣传。

  • 互联网飞速发展推动Go在国内落地

中国已经是事实的移动互联网时代的领军者,大量创业公司如雨后春笋般诞生。而Go对于startup企业来说是极其适合的。开发效率高,满足了Startup企业对产品或服务快速发布的需求;运行效率高可以让startup公司节省初期在硬件方面的投入:一台主机顶住100w并发。

对于那些巨头、大公司而言,Go又是云计算时代基础设施的代表性语言,自然也会投入到Go怀抱,比如:阿里CDN、百度门户入口、滴滴、360等。

8、对于刚开始学习 Go ,并期待将其应用在项目中的新人们,您有哪些建议?

学语言,无非实践结合理论。

  • 理论:书籍和资料

这里转一下我在知乎上一个回答

强烈推荐:Rob Pike 3-day Go Course,虽然语法过时了,但看大师的slide,收获还是蛮多的。

Go基础: Go圣经《The Go Programming Language》和《Go in Action》。
原理学习: 雨痕的《Go学习笔记》。
Go Web编程: 直接看astaxie在github上的《Go web编程》。

还有一本内容有些旧的,但个人觉得值得一看的书就是《The Way To Go》,大而全。Github上有部分章节的中译版

另外,建议看一遍官方的Language specificationeffective gogo faq,对学go、理解go设计的来龙去脉大有裨益。

  • 实践:多读多写Code

多读代码:首选标准库,因为Go的惯用法和最佳实践在标准库中都有体现。

写代码:这个如果有项目直接实践那是非常的幸福;否则可以从改写一个自己熟悉领域的工具开始。比如:以前我刚接触Go的时候,没啥可写的。就改写一套cmpp协议实现。后来做wechat接口,实现了一个简单的wechat基本协议,当然这两个代码也过于陈旧了,代码设计以及其中的go语言用法不值得大家学习了^0^。


微博:@tonybai_cn
微信公众号:iamtonybai
github.com: https://github.com/bigwhite

搭建你自己的Go Runtime metrics环境

自从Go 1.5开始,每次Go release, Gopher Brian Hatfield都会将自己对新版Go的runtime的性能数据(与之前Go版本的比较)在twitter上晒出来。就连Go team staff在世界各地做speaking时也在slide中引用Brian的图片。后来,Brian Hatfield将其用于度量runtime性能数据的代码打包成library并放在github上开源了,我们也可以使用这个library来建立我们自己的Go Runtime metrics设施了。这里简要说一下搭建的步骤。

一、环境与原理

Brian Hatfield的go-runtime-metrics library实现的很简单,其runtime data来自于Go runtime package中的MemStats、NumGoroutine和NumCgoCall等。被测试目标程序只需要import该library即可输出runtime states数据:

import _ "github.com/bmhatfield/go-runtime-metrics"

go-runtime-metrics library将启动一个单独的goroutine,并定时上报runtime数据。目前该library仅支持向statsD输出数据,用户可以通过配置将statsD的数据导入graphite并使用graphite web查看,流程如下图:

img{512x368}

本次实验环境为ubuntu 16.04.1:

$ uname -rmn
tonybai-ThinkCentre-M6600s-N000 4.4.0-83-generic x86_64

二、搭建步骤

1、安装go-runtime-metrics library

我们直接go get就可以下载go-runtime-metrics library:

$ go get github.com/bmhatfield/go-runtime-metrics

我们编写一个目标程序:

//main.go
package main

import (
    "flag"
    "log"
    "net/http"
    "os"

    _ "github.com/bmhatfield/go-runtime-metrics"
)

func main() {
    flag.Parse()

    cwd, err := os.Getwd()
    if err != nil {
        log.Fatal(err)
    }

    srv := &http.Server{
        Addr:    ":8000", // Normally ":443"
        Handler: http.FileServer(http.Dir(cwd)),
    }
    log.Fatal(srv.ListenAndServe())
}

我的ubuntu主机上安装了四个go版本,它们分别是go 1.5.4、go 1.7.6、go 1.8.3和go1.9beta2,于是我们分别用这四个版本的server作为被测程序进行go runtime数据上报,以便对比。

$ GOROOT=~/.bin/go154 ~/.bin/go154/bin/go build -o server-go154 main.go
$ GOROOT=~/.bin/go174 ~/.bin/go174/bin/go build -o server-go174 main.go
$ GOROOT=~/.bin/go183 ~/.bin/go183/bin/go build -o server-go183 main.go
$ GOROOT=~/.bin/go19beta2 ~/.bin/go19beta2/bin/go build -o server-go19beta2 main.go

$ ls -l

-rwxr-xr-x 1 tonybai tonybai 6861176 7月   4 13:49 server-go154
-rwxrwxr-x 1 tonybai tonybai 5901876 7月   4 13:50 server-go174
-rwxrwxr-x 1 tonybai tonybai 6102879 7月   4 13:51 server-go183
-rwxrwxr-x 1 tonybai tonybai 6365648 7月   4 13:51 server-go19beta2

2、安装、配置和运行statsD

statsD这个工具用于收集统计信息,并将聚合后的信息发给后端服务(比如:graphite)。statsD是采用js实现的服务,因此需要安装nodejsnpm和相关modules:

$ sudo apt-get install nodejs
$ sudo apt-get install npm

接下来,我们将statsD项目clone到本地并根据exampleConfig.js模板配置一个我们自己用的goruntimemetricConfig.js(基本上就是保留默认配置):

// goruntimemetricConfig.js
{
  graphitePort: 2003
, graphiteHost: "127.0.0.1"
, port: 8125
, backends: [ "./backends/graphite" ]
}

启动statsD:

$ nodejs stats.js goruntimemetricConfig.js
3 Jul 11:14:20 - [7939] reading config file: goruntimemetricConfig.js
3 Jul 11:14:20 - server is up INFO

启动成功!

3、安装、配置和运行graphite

graphite是一种存储时序监控数据,并可以按用户需求以图形化形式展示数据的工具,它包括三个组件:

whisper是一种基于file的时序数据库格式,同时whisper也提供了相应的命令和API供其他组件调用以操作时序数据库;

carbon用于读取外部推送的metrics信息,进行聚合并写入db,它还支持缓存热点数据,提升访问效率。

graphite-web则是针对用户的图形化系统,用于定制展示监控数据的。

Graphite的安装和配置是略微繁琐的,我们一步一步慢慢来。

a) 安装graphite

$sudo apt-get install graphite-web graphite-carbon

whisper将作为依赖自动被安装。

b) local_settings.py

graphite的主配置文件在/etc/graphite/local_settings.py,文件里面有很多配置项,这里仅列出有关的,且本次生效的配置:

// /etc/graphite/local_settings.py

TIME_ZONE = 'Asia/Shanghai'

LOG_RENDERING_PERFORMANCE = True
LOG_CACHE_PERFORMANCE = True
LOG_METRIC_ACCESS = True

GRAPHITE_ROOT = '/usr/share/graphite-web'

CONF_DIR = '/etc/graphite'
STORAGE_DIR = '/var/lib/graphite/whisper'
CONTENT_DIR = '/usr/share/graphite-web/static'

WHISPER_DIR = '/var/lib/graphite/whisper'
LOG_DIR = '/var/log/graphite'
INDEX_FILE = '/var/lib/graphite/search_index'  # Search index file

DATABASES = {
    'default': {
        'NAME': '/var/lib/graphite/graphite.db',
        'ENGINE': 'django.db.backends.sqlite3',
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': ''
    }
}

c) 同步数据库

接下来执行下面两个命令来做database sync(同步):

$ sudo graphite-manage migrate auth
.. ....
Operations to perform:
  Apply all migrations: auth
Running migrations:
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0001_initial... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK

$ sudo graphite-manage syncdb

Operations to perform:
  Synchronize unmigrated apps: account, cli, render, whitelist, metrics, url_shortener, dashboard, composer, events, browser
  Apply all migrations: admin, contenttypes, tagging, auth, sessions
Synchronizing apps without migrations:
  Creating tables...
    Creating table account_profile
    Creating table account_variable
    Creating table account_view
    Creating table account_window
    Creating table account_mygraph
    Creating table dashboard_dashboard
    Creating table events_event
    Creating table url_shortener_link
    Running deferred SQL...
  Installing custom SQL...
Running migrations:
  Rendering model states... DONE
  Applying admin.0001_initial... OK
  Applying sessions.0001_initial... OK
  Applying tagging.0001_initial... OK

You have installed Django's auth system, and don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'root'):
Email address: xx@yy.com
Password:
Password (again):
Superuser created successfully.

这里我们创建一个superuser:root,用于登录graphite-web时使用。

d) 配置carbon

涉及carbon的配置文件如下,我们保持默认配置不动:

/etc/carbon/carbon.conf(内容太多,这里不列出来了)

/etc/carbon/storage-schemas.conf
[carbon]
pattern = ^carbon\.
retentions = 60:90d

[default_1min_for_1day]
pattern = .*
retentions = 60s:1d

[stats]
pattern = ^stats.*
retentions = 10s:6h,1min:6d,10min:1800d

carbon有一个cache功能,我们通过下面步骤可以将其打开:

打开carbon-cache使能开关:

$ vi /etc/default/graphite-carbon
CARBON_CACHE_ENABLED=true

启动carbon-cache:

$ sudo cp /usr/share/doc/graphite-carbon/examples/storage-aggregation.conf.example /etc/carbon/storage-aggregation.conf
$ systemctl start carbon-cache

e) 启动graphite-web

graphite-web支持多种主流web server,这里以apache2为例,graphite-web将mod-wsgi方式部署在apache2下面:

$sudo apt-get install apache2 libapache2-mod-wsgi

$ sudo service apache2 start

$ sudo a2dissite 000-default
Site 000-default disabled.

$ sudo service apache2 reload

$ sudo cp /usr/share/graphite-web/apache2-graphite.conf /etc/apache2/sites-available

$ sudo  a2ensite apache2-graphite
Enabling site apache2-graphite.
To activate the new configuration, you need to run:
  service apache2 reload

$ sudo systemctl reload apache2

由于apache2的Worker process默认以www-data:www-data用户权限运行,但数据库文件的访问权限却是:_graphite:_graphite:

$ ll /var/lib/graphite/graphite.db
-rw-r--r-- 1 _graphite _graphite 72704 7月   3 13:48 /var/lib/graphite/graphite.db

我们需要修改一下apache worker的user:

$ sudo vi /etc/apache2/envvars

export APACHE_RUN_USER=_graphite
export APACHE_RUN_GROUP=_graphite

重启apache2生效!使用Browser打开:http://127.0.0.1,如无意外,你将看到下面graphite-web的首页:

img{512x368}

三、执行benchmarking

这里我将使用wrk这个http benchmarking tool分别对前面的四个版本的目标程序(server-go154 server-go174 server-go183 server-go19beta2)进行benchmarking test,每个目标程序接收10分钟的请求:

$ ./server-go154
$ wrk -t12 -c400 -d10m http://127.0.0.1:8000

$ ./server-go174
$ wrk -t12 -c400 -d10m http://127.0.0.1:8000

$ ./server-go183
$ wrk -t12 -c400 -d10m http://127.0.0.1:8000

$ ./server-go19beta2
$ wrk -t12 -c400 -d10m http://127.0.0.1:8000

四、结果展示

用浏览器打开graphite-web,在左边的tree标签下以此打开树形结构:Metrics -> stats -> gauges -> go -> YOUR_HOST_NAME -> mem -> gc -> pause,如果顺利的话,你将会在Graphite Composer窗口看到折线图,我们也以GC pause为例,GC pause也是gopher们最为关心的:

img{512x368}

通过这幅图(左侧坐标轴的单位为nanoseconds),我们大致可以看出:

Go 1.5.4的GC pause约在600μs左右;
Go 1.7.4的GC pause约在300μs左右;
Go 1.8.3和Go 1.9beta2的GC pause基本都在100μs以下了。Go 1.9的GC改进似乎不大。不过这里我的程序也并不足够典型。

其他结果:

Go routines number:

img{512x368}

GC count:

img{512x368}

memory allocations:

img{512x368}

除了查看单个指标曲线,你也可以通过graphite-web提供的dashboard功能定制你要monitor的面板,这里就不赘述了。

五、参考资料


微博:@tonybai_cn
微信公众号:iamtonybai
github.com: https://github.com/bigwhite




这里是Tony Bai的个人Blog,欢迎访问、订阅和留言!订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:


如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:


以太币:


如果您喜欢通过微信App浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:



本站Powered by Digital Ocean VPS。

选择Digital Ocean VPS主机,即可获得10美元现金充值,可免费使用两个月哟!

著名主机提供商Linode 10$优惠码:linode10,在这里注册即可免费获得。

阿里云推荐码:1WFZ0V立享9折!

View Tony Bai's profile on LinkedIn


文章

评论

  • 正在加载...

分类

标签

归档











更多