Go的CICD、Module、构建、测试

前言

最近在做一些项目的重构,将一些服务和功能逻辑逐渐迁移到Go,或者通过来来重写一遍。一是优化相关逻辑,删减部分代码和逻辑功能,二是之前的架构和服务的部署方式,已经远远落后于时代,不论是开发效率、代码检查、部署与发布上线等等,都消耗了大量不必要的时间,严重影响开发效率。

CICD有很多方案,如Drone、Jenkins、Gitlab等,过往的经历告诉我,不能单纯为了Go而使用Go,除非Go编写的服务确实好用,足够成果。从简单实现的角度,通过Gitlab来完成,公司的部署环境有些特殊,有安全层面的考虑,是不能直接访问外网的,包括但不限于docker pull、go get、go mod download等等。如何加快CI的执行速度,如何使得构建后的镜像最小,减少传输带宽,如何复用Go相关的package,减少多次构建需要重新下载等等,就这些问题分享一下我的思路和做法。

镜像构建

docker对大家来讲,已经非常常见了,并不是什么新潮的东西。但经常能看到大家构建出来的镜像,并不是最佳实践,构建出来的镜像包含了很多不必要的内容,尤其是如果这个镜像作为基础镜像需要给其他人使用的,那么这就很不负责任了。我只是跑一个简单的服务,你却需要我docker pull一个4GB的镜像,要花大量时间等待,尤其是网络不好的时候,编译发布也不方便。
如何构建出一个体积最小的镜像,这是我们需要对自己的基本要求,也是一个基本良心。

合并多个RUN语句

看过大量的Dockerfile都会发现,很多Dockerfile都用了一些奇怪的技巧,用了大量的&&,来替代多个RUN,因为根据docker镜像构建的原理,其实就和git commit一样,是逐层叠加的,层数越多,占用的空间也就会越大。

多阶段构建

若多个阶段使用同个镜像,那么多阶段构建等于压缩了中间多个层,将他们合并到一个层。如我们在git中add了一个较大的文件,然后下一次commit的时候把他删除了,虽然我们拉取这个git代码时,这个文件不在了,但是他一直存在在这个仓库,还是会占用较大的体积。所以我们做的ADD data ./RUN rm ./data,其实就是个障眼法,掩耳盗铃,这个data还是存在于镜像中。所以可以在移除掉之后,通过多阶段构建,将结果COPY一份,不需要中间过程产生的文件等。

1
2
3
4
5
6
7
FROM golang:1.12 as build-env
WORKDIR /go/src/y.cn/some
ADD . ./
RUN CGO_ENABLED=0 GO111MODULE=on go build -ldflags -o some y.cn/some
FROM golang:1.12
WORKDIR /go
COPY --from=build-env /go/src/y.cn/some/some ./

上述脚本已经将所编译的some,copy到一个新的镜像,这就是一个简单合并各个镜像层。

distroless

这是Google提供的一个容器库,支持多个主流语言,仅包含该语言所需的环境、二进制文件和脚本,他甚至shell都没有,所以你想attach进去容器都是不行的,当docker相关的日志和监控比较完善的时候,才有条件使用。

Alpine

Alpine是各类镜像使用最多的基础镜像,Alpine是一个轻量级、面向安全的linux发行版,也是比较实用的镜像中最小的一个,如最新的3.10版本,仅有5MB大小。如Go开发的脚本、服务,可以将二进制文件构建好后,copy到一个干净的Alpine镜像中,这样得到的镜像大小就特别小,约等于Alpine镜像大小+Go二进制包大小。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
FROM golang:1.12 as build-env
WORKDIR /go/src/y.cn
RUN git clone git@y.cn:some.git --depth 1 \
&& cd some \
&& CGO_ENABLED=0 GO111MODULE=on go build -ldflags -o some y.cn/some

FROM alpine:3.10
RUN apk update \
&& apk upgrade \
&& apk add --no-cache \
ca-certificates \
&& update-ca-certificates 2>/dev/null || true
WORKDIR /data
COPY --from=build-env /go/src/y.cn/some/some ./
ADD conf.yml ./etc
ENTRYPOINT ["./SERVICE_NAME"]

这样就是得到了一个非常小的镜像,通常10~30MB的一个镜像就能将服务容器跑起来。因为Alpine是非常小的,所以并不支持gcc环境等,需要CGO_ENABLED=0关闭CGO,不然你会发现编译后的二进制包无法运行。

Go Module

Go Mod是Go新引入的一个包管理工具,实际上谈不上成熟,官方也没有推荐使用,但go mod毕竟还是未来,提前做好准备还是十分必要的。原先的GoVendor/GoDep的包管理,并未在部署上尝试特别大的问题。但由于go mod下载的package其实是放在你的$GOPATH/pkg/mod中,并没有加载到你的项目中,go mod vendor我执行之后也并未成果,暂时没找到什么原因。
所以使用go mod也带来一个挑战,事实上很多服务器的环境,并没有一个放开的公网网络,若 package之前未层使用过,go build或者go mod download的时候,都需要下载对应的package。意味着给Go项目的CICD、测试带来了一些影响。
在如何解决这类问题方面,分享一下我的看法,无非就是线上环境的$GOPATH/pkg/mod需要提前准备好相关package的问题。想到了可以通过golang:latest作为基础镜像,把项目git仓库ADD进去,go mod download下载所有所需的package,然后删掉git库,commit这个镜像到线上,那线上就有pkg/mod了。然后这个镜像就可以作为线上构建的基础镜像,包含所需的库,并且提供一些必备的工具脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
FROM golang:1.12 as build-env
WORKDIR /go/src/y.cn/some
ADD . ./
RUN GO111MODULE=on go mod download \
&& cd ../ \
&& rm -rf some
FROM golang:1.12
WORKDIR /go
RUN apt-get update && apt-get install -y mariadb-client > /dev/null
RUN go get golang.org/x/tools/cmd/goimports \
&& go get honnef.co/go/tools/cmd/staticcheck \
&& go get github.com/golangci/golangci-lint/cmd/golangci-lint
COPY --from=build-env /go/ ./

Gitlab Runner

通常很多公司的内部仓库都是用的Gitlab来管理,那么其实Gitlab是能够关联一些很好的工具,比如一些需求管理、Wiki等。其中Gitlab CI可以做一些代码检查、跑测试用例、自动构建等等工作。使得每个人的代码提交后,都能检测本次提交改动内容的正确性,合并到主线分支之后,是否所有测试用例都能通过,从而提前避免一些代码错误、上线故障等。
尤其是如果团队人数很多,一个大项目下面很多微服务,各个服务之间存在交叉影响,能够完善测试各个数据库、缓存之间的交互,模拟流量和数据,在一个小型环境中跑通全部测试用例,这对开发效率是非常有意义的。每个人只需要关注自己修改的功能,并编写测试用例来保证自己的功能(逻辑)不受其他人提交的代码影响,而不需要花太多精力来留意别人写的模块。
Gitlab CI依靠Gitlab Runner来运行,Gitlab Runner可以通过docker容器来运行,可以配置最大任务数限制,当有git commit的时候,他就会拉取最新的代码,对这批代码做一些CICD操作,这些配置命令,可以写在.gitlab-ci.yml,Gitlab Runner会按这个配置来执行这些计划任务。当测试不通过的时候,会发送邮件到对应的邮箱。
对应的Dockerfile其实也可以很简单:

1
2
3
FROM gitlab/gitlab-runner:latest
WORKDIR /
COPY ./config.toml /etc/gitlab-runner

Gitlab Runner的注册其实也很简单,可以先起一个空镜像容器,运行sudo gitlab-ci-multi-runner register,输入gitlab的链接、Token、Runner的名字、类型等等,就会生成一个如下的配置,这个配置可以保存下来,将其提交到镜像中,这个容器就可以发布到线上了。其中concurrent表示同时运行的任务数,pull_policy等拉取规则可以定制化修改一下。
需要特别留意的是,docker的sock文件是需要挂载进镜像的,以便Gitlab Runner能够运行各类docker镜像来跑Gitlab的CI。
配置参考:

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
concurrent = 6
check_interval = 0

[session_server]
session_timeout = 1800

[[runners]]
name = "CI-name"
url = "https://git.y.cn/"
token = "xxxx"
executor = "docker"
[runners.custom_build_dir]
[runners.docker]
tls_verify = false
image = "golang:lastest"
memory = "4g"
cpus = "4"
privileged = false
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
pull_policy = "if-not-present"
shm_size = 0
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.custom]
run_exec = ""

通过docker命令可以将gitlab runner启动docker run --net=host --rm -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest,这时候任何满足规则的commit都会触发Gitlab CI。可以根据不同的语言来配置不同的.gitlab-ci.yml,根据项目的特性来编写一些定制化的检查。

最近一些感想

最近还是提了离职,其实这个想法考虑了很长时间,也确实是经过慎重思考之后才决定的。时间不长不短,不到两年的时间内,对广告行业有了长足的认识,在期间也通过实际行动做到了用科技改变生活、促进流水提升,能制定适宜业务的技术实现方案、架构调整等等,2年来最大的收获不仅仅是技术能力的提升,更重要的是业务思维。离开广告行业其实也是有些不舍的,但套用另一个同事的话来讲,哪有什么不舍的,都是打工,找到自己最舒适、最开心的活法才是更重要的。
临走之际,其实往往都会有很多谈话。譬如聊聊你在公司觉得有哪些让你觉得不舒服的地方、你觉得可以改进的问题、你对这个业务的看法、离职的原因是什么,甚至会问问你有没有挽回的余地。离职的理由往往千万种,上班太早,领导太傻逼,工作太无聊,没啥成就感,工作安排不合理,业务太烦,高层不靠谱,不懂管理、看不到希望、钱没给够等等都是理由。
一份工作,主要靠三点来维持,相处的人、工作内容、薪酬,三者缺二不可,只要任意两点崩塌,就没法继续待下去了。2年前的一个同事群,一共9个人,现在已经只剩下2个人。这个行业流动性还是很高的,没有谁离了谁就不行了。
薪酬、职级没调整,是比较直接的原因之一,不少同事在有米的时间已经很长很长了,对这些同事而言,有米是第一份工作,也是倾注了蛮多情感的家,有米的技术栈其实都比较前沿,技术同学的能力都还不错,广州的技术公司并不多,圈子就这么大,有米的同学们还是很有市场竞争力。早些年的有米还是很不错的,弹性的考勤制度、双休、少加班(至少不强制),这种制度比较考验主动性,是建立在一个互相信任的基础上的,相对扁平化的管理,自由的环境。近两年公司的一系列战略性错误,对业务、产品的短视,不接底气的制度,都是近两年人才流失、业务方向迷失的根本原因。一个公司堕落的开始,都是注重考勤,开始过分关注员工的上班时间,加班情况,又缺乏激励,缺乏对自身实力与定位的了解,没有关注员工的自身发展,没有一个适宜的绩效评定。不懂业务的高层,不接地气的考勤制度,不尊重市场规律,朝更暮改的战略方向。高层想法变得太快,过于随意,普通同学其实是很累的,并不是大家不够努力,而且方向不对。有米并不是一个大公司,但似乎所有大公司有的弊病,都不少。
其实不管是平时的工作,还是离职的例行问答,我的回答都是很直接、直率的,也会经常与leader交换一下看法和意见,沟通所有关键问题的想法和gap,并解决这类问题。这些都是中层能直接解决的问题,并且都解决的不错,我们也找到很好的协作方式,确实做出了较好的成绩。但高层其实很少聆听他人的意见,不管是业务方向上还是公司经营方式,反馈最多的考勤问题,就直接置之不理,带着这种傲慢与偏见。广州的早高峰特别挤,挤到你怀疑人生,挤到你根本就不想去上班,然而你去到公司楼下,还要多排队15-20分钟等电梯,可能你会怀疑早到这点时间能做什么,毕竟同学们付出了大于半个小时通勤时间的成本。
广告行业其实是一个非常朝气蓬勃的行业,当你自己遇到问题了,可以了解市场和同行的情况,你应该反思自己是不是哪里做得不对,而不是责怪行情、市场,往往不是这个市场不行了,而是你不行了。看看别家的年会与年终奖,不要责怪大环境,经济再差也有大把赚钱的公司,好的技术根本不愁工作。找不到工作的都是各个行业的底层。

技术的价值

以前我一直在思考技术的价值在哪里,有哪些别人所不具备的优势,最近似乎得到了一些答案。纵观很多技术经理、技术总监,有的很懂业务,但缺乏技术架构认识,很难管住其他的技术,想法、关注点与实际也有些差距,就很难维持一个高效稳定业务系统,有的技术可能很强,但缺乏对业务的理解,重心放在技术代码的提升,如何规范化,如何提升技术的能力等等,但其实会发现,如果你缺乏对业务的了解,你的技术再好,方向错了,业务场景发生了变化,再多的努力都是无用功。做技术、做架构,我认为都不应该脱离业务思维,脱离了业务思维的架构师,往往会给你一个很高大上的架构,他确实很好,技术也很厉害,但不适合这个业务。
作为技术负责,如何使用有限的资源,做更多、更大的事情,这才是我们的价值体现。资源永远都是稀缺的,如果有1000个bug和100个紧急的业务需求,你如何判断哪50个是最重要、最迫切的。这要求你需要具备行业敏锐度,有判断能力,了解你的业务场景是面向哪些用户,你的用户群体最在意的是什么?你要建造的是一栋大厦,而不仅仅是一堵墙,这面墙有些瑕疵,但并不影响你这栋大楼的按期交付,别把大量的时间耗费在这些小事上面。
靠谱的程序员很难得,你交给他一个需求,他会先判断这个需求的合理性、场景,有争议部分事先充分沟通,制定一个适宜的方案,跟需求方确认这个方案的预期,开发,并且做足测试,确认功能的完整性,和需求方一起验收需求,通过数据回顾功能的作用,并能主动做出一些优化、提出一些建议。能做到这些的,都是非常靠谱的技术,你会很信任他,愿意把更多更重要的事情,交给他负责。

对海外市场看法

海外其实是一个非常有前景的市场,毕竟除了中国,其他的都算海外,市场够大(😄),尤其是新兴市场,你可以照搬你以往的成功经验,适当改造,通过一些接地气的方案,就能在一个新的市场收割一波。再从汇率角度考虑,比如你在美国市场赚2美元,换回来就是14元了,比起外国公司,坐拥廉价的中国劳动力,还能在美国、欧洲等这些海外市场同台竞争,这就是一种网络倾销。
只要你的业务广,这就像是一个风投,多方押注,总会有一个成功的,东方不亮西方亮,这个市场不成功,换一个市场再尝试一次。成功一个就能收回一切成本,并且大赚一笔,而且没有什么市场准入、政策风险。

回顾与展望

2018年总结

这一年的目标还是没有实现,看书没有看多少,甚至去图书馆的次数也少了很多,背英语单词坚持了小半年,但没有坚持下去。早睡早起也没有做好,还是比较迟才睡觉,这里有工作的原因,也有自己生活习惯的原因。但在极简方面做得还是不错,减少了很多不需要、多余的物品。演唱会没有去,这一年去了日本旅游,也去了成都旅游,在峨眉山看雪,也去了香港若干次,其中两次在香港徒步与露营,走了香港比较著名的麦理浩径,也去了香港最南的蒲台岛。
这一年也取得了一些不便公开的成果。这一年在业务上更加深入了,对广告行业也有了一定的了解,但感觉在技术上感觉没有特别大的进步、成就感,所以接下来要加强技术学习。

回顾过往,继续制定2019年计划。

2019计划

家庭生活计划

  • 周三美食日 (吃顿大餐)
  • 周四总结日 (回顾本周计划执行情况)
  • 周六活动日 (执行旅游计划中的短期任务、爬山、远足,因不可抗力可调整为其他积极向上的活动)
  • 周日学习日 (看书、学习)

娱乐休闲计划

  • 日本旅游
  • 深圳游玩
  • 香港游玩
  • 澳门游玩
  • 短期旅游(城市本地景点活动探索)

每日时间表

  • 早起运动,不能起太晚
  • 早起喝一杯白开水
  • 刷牙听歌洗澡洗头
  • 出门上班,希望能直接骑共享单车到地铁站,不要坐公交换乘
  • 地铁上通过Telegram阅读过去一天技术领域的发展与新闻
  • 上班做好每天工作计划
  • 睡前喝杯牛奶,刷牙洗脸洗澡上床

财富增长计划

  • 提升技术能力,不断学习新技术,并在生产环境中实践
  • 在证券投资方面,继续原有的持股策略,继续加大投入,并获取更大的财富
  • 开通港股通,通过上交所买卖香港地区上市的股票
  • 控制流动资金的比例,并做好流动资金增长计划

行为习惯提升计划

  • 不断跳出心理舒适区
  • 多聆听,多接纳多方意见
  • 多赞扬肯定对方
  • 严格要求自己,对他人要多宽容
  • 态度要温和

体重增长计划

  • 定期执行超市采购计划,保证家里任何时候都有吃的
  • 每天下午增加一个下午茶
  • 要多吃,辅助定期运动

每周细分计划

  • 看2本书(细化)
  • 看1部电影
  • 1次跑步运动
  • 1次爬山或远足
  • 看1集美剧(定期刷新剧目)
  • 看1次以上指定节目(细化列表)

写于证券投资5年之余

上大学时,学业之余总是特别的乏味。了解我的人都知道,我几乎不玩游戏,大学四年间,我拜读了图书馆所有我想看的书籍。出于对新书的偏好,我认为一本书如果真的有价值,那么一定会再版的,读旧书容易浪费时间。在每周五图书馆上新日,我都会把感兴趣的新书一扫而空。我的业余兴趣特别广泛、不论是数学、计算机、经济学、心理学等社科都有涉猎,从小就读了很多很杂很杂,可能对我一生都不会有什么作用的书。
真正接触证券投资还是从2013年开始,当我满足开立账户的条件,就去开立了证券账户。性格上,我是还是倾向于风险规避(risk aversion),我更倾向于承担更小的风险,实现相对没有那么大,但不那么低的年化收益率。证券投资领域,外行跟内行差距很大,认识的很多同事,虽然也买卖股票很多年,但其实并没有总结经验,也没有形成自己的投资策略或方法论。这种就像古代的中国人,只注重应用,却没有提炼出其基础理论,永远只能停留在“野蛮人”时代。
证券投资之前,投资过一段时间比特币,毕竟当时未成年,A股开户都开不了,这段经历,让我有了诸多体会,也快速进入了投资市场。大学期间参与了大学一个技术实验室,在技术之余,我们会聊及历史、人文、投资。通过一师兄了解到了比特币,当时比特币市值500元,于是我尝试性的投资了一笔小钱,最终涨到700元的时候,我就hold不住卖掉了,这也算是实现了40%的一次收益率,这段时间仅仅几个星期。多年后,比特币涨到了1万多美元,当年交易剩余的尾数,也价值几十元了。
投资证券这几年,倒是从未想到要通过证券实现财富自由,这也不现实,给自己的定位就是挣点小钱,争取不大亏,为后面的更多年,积累经验。我的操作频率很低,可能一年就买卖几次,一个月也不见得有一次买卖。操作手法也很简单,选一些市值高、市净率低、优质的上市公司,价格低的时候买,涨了就卖,套了就隔一段时间补一些,反正自己的钱又不急用,挣那么多钱也没处花。

转变

从2013年开立证券账户,转眼间5年时间已经过去,已经成为名副其实的老股民了。今年开始计划承担更大的风险,尝试一些过去没有做的操作。

新的一年,生活要过得有仪式感

2017这一年

2017年即将过去,现在回顾发现,这一年不管是年初定的目标,还是年中的想法,都没有完全实现。
过去这一年,面临着许多挑战与混乱。
很多时候,事物的发展,并不像我们预先设想的那样,但我认为一个有效的全年计划,还是非常重要。
写新年计划这个想法,也是受到同学的启发。

设想

以后每年新年来临之际,我都会写一个新年计划,一是看看过去一年的想法实现了多少,二是展望一下未来。算是一个自我总结,改进且不断进步,也是一个对自我优化迭代的一个过程。
我也希望我能回到大学时的状态,保持一定的阅读量。一个勇敢、坚定、有目标且不断奋斗的自己。

2018

  • 看200本书,记录书单及读书笔记
  • 保持背英语单词的习惯
  • 加强锻炼与膳食均衡,BMI指数达标
  • 不断学习(计算机、数学、英语)
  • 早睡早起,不熬夜(11-7)
  • 认识20个优秀的人
  • 找到1个有趣的对象
  • 通过学习取得1个证书
  • 定期淘汰旧东西,执行极简生活理念
  • 做20件新鲜事
  • 看一场演唱会

    家庭生活计划

  • 周四总结日 (回顾本周计划执行情况)
  • 周五美食日 (吃顿大餐)
  • 周六活动日 (执行旅游计划中的短期任务)
  • 周日运动日 (爬山,远足)

    娱乐休闲计划

  • 环球旅游计划探索
  • 日本旅游
  • 深圳游玩
  • 香港游玩
  • 澳门游玩
  • 台湾旅游
  • 探索1~3个未知但意思的景点
  • 短期旅游(城市本地景点活动探索)
  • 学10首外语歌
  • 学20首华语歌

    每日时间表

  • 早起喝一杯白开水
  • 刷牙听歌洗澡洗头
  • 出门上班,希望能直接骑共享单车到地铁站,不要坐公交换乘
  • 地铁上通过Telegram阅读过去一天技术领域的发展与新闻
  • 上班做好每天工作计划
  • 睡前喝杯牛奶,刷牙洗脸洗澡上床

    财富增长计划

  • 提升技术能力,不断学习新技术,并在生产环境中实践
  • 在证券投资方面,继续原有的持股策略,但转变为长期持有,不谋求短期利益
  • 探索能否在美股或港股中操作
  • 控制流动资金的比例,并做好流动资金增长计划

    行为习惯提升计划

  • 不断跳出心理舒适区
  • 多聆听,多接纳多方意见
  • 多赞扬肯定对方
  • 严格要求自己,对他人要多宽容

    体重增长计划

  • 定期执行超市采购计划,保证家里任何时候都有吃的
  • 每天下午增加一个下午茶
  • 要多吃,辅助定期运动

    每周细分计划

  • 学习一个好习惯,记录并执行
  • 看4本书
  • 看2部电影
  • 1次跑步运动
  • 1次爬山或远足
  • 看5集美剧

influxDB的使用与优化

官方配置要求

influxDB是为SSD运行设计的,如果服务器硬盘不是固态硬盘,那么按照官方的说法是不推荐的。
series(维度)是influxDB的一个比较重要的指标,维度越多,所需要的索引也就越大。

备份与还原

使用中发现有时候,influxDB的备份是可以分数据库的,但是还原导入的data会有不认的情况,就是meta中没有读取data中的数据。

还原influxDB

1
influxd restore -database xxxdatabase -datadir /data/influxdb/data ./

这时候在新的influxDB库执行

1
influx_inspect export -database xxxdatabase -datadir /data/influxdb/data/ -waldir /data/influxdb/wal/ -out xxxdatabase

重新将数据导入,并且修改meta元数据

1
influx -import -path=xxxdatabase

这时候就将xxxdatabase,从对应的/data/influxdb/data/与/data/influxdb/wal/输出到文件xxxdatabase中了。

数据维度

统计database的数据维度

1
influx -database 'xxxdatabase' -execute 'show series' -format 'csv'| wc -l

统计具体measurement的数据维度

1
influx -database 'xxxdatabase' -execute 'show series from xxxmeasurement' -format 'csv'| wc -l

openSUSE快照与回滚

前因

作死升级了openSUSE的一个不稳定版本,于是整个系统都挂掉了,无法开机。联想到snapper有个很强大的快照及恢复功能,然后一边摸索一边寻找方法恢复。

首先,要在开机的高级菜单中,选择一个最近的,能打开的快照Read Only快照。
如果不能进入系统,再选择更新的,不断重复。
如果能顺利进入系统,则执行

1
snapper rollback xxx

其中xxx为当前的版本号

再次重启发现能直接进入了,但你可能会发现丢掉了部分数据,这是因为快照内容不全导致的,这时候,执行

1
snapper -v undochange aaa..bbb

其中bbb为当前最新版本,aaa则是你要回滚的版本,这样系统就会恢复到aaa这个状态,把aaa至今的所有变更回滚。

升级变化

ifconfig,arp,netstat,route被移除出net-tools
需额外安装net-tools-deprecated

编译VIM8

编译错误

1
2
3
4
5
6
7
8
9
10
checking --with-tlib argument... empty: automatic terminal library selection
checking for tgetent in -ltinfo... no
checking for tgetent in -lncurses... no
checking for tgetent in -ltermlib... no
checking for tgetent in -ltermcap... no
checking for tgetent in -lcurses... no
no terminal library found
checking for tgetent()... configure: error: NOT FOUND!
You need to install a terminal library; for example ncurses.
Or specify the name of the library with --with-tlib.

安装必要的包

1
zypper in ncurses-devel python-devel

安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
./configure --with-features=huge \
--enable-multibyte \
--enable-rubyinterp=yes \
--enable-pythoninterp=yes \
--with-python-config-dir=/usr/lib64/python2.7/config \
--enable-python3interp=yes \
--with-python3-config-dir=/usr/lib64/python3.4/config \
--enable-perlinterp=yes \
--enable-luainterp=yes \
--enable-gui=gtk3 \
--enable-cscope \
--prefix=/usr

make
make install

Protocol Buffers 一种轻便高效的结构化数据存储格式

介绍

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。

安装

安装过程中,参考了Google Protocol Buffer 的使用和原理Protobuf

了解到了下面几点:

  1. 该项目的 php 语言版本,可通过纯 php 包和本地 c 扩展来运行启动;
  2. 纯 php 包是为了提供在 php 平台上更广的可用性,而 c 扩展更注重性能;
  3. 两者的实现,提供了同一套 APIs ,应该是由同一套代码生成的;
  4. 如果用户想在他们两者之间切换,不需要重新修改/生成代码;
  5. 两者都实现了通过生成 php 代码来实现在 php 中的 message 和 enum 类型;
  6. 作者建议通过 php 来生成,支持 .proto 文件;
  7. 这个包的构建过程仅在当前目录安装扩展/包,其次还要安装该协议的编译包去最终完成 php 生成功能。

体会

了解之后,感觉实现起来还是比较麻烦,毕竟很多项目其实已经用了很久了,rpc 接口众多,一下子迁移起来其实是比较困难的。如果是新建的项目倒是可以尝试,但是每次都需要预先定义这些数据结构,其实也是带来一定的难度,因为数据结构可能会不断的变化。理论上 google 的这个协议是让不同的语言不必去例会数据结构,而只需要关注具体的数据。但是代码毕竟还是人来写的,其实用起来反而不如 json 这些标准化跨平台包含数据结构的格式。

感觉暂时还不适合在大项目中使用,毕竟开发不仅仅是一个人,而是一个团队。

如何反爬虫及恶意采集

前言

恶意采集、攻击及非搜索引擎爬虫,影响了服务器的网络,同时也有可能暴露一些存在风险/SQL注入的网站。

我们虽然是识别出了,但是他们的抓取还是没有停止,有时候一天就是上百万次,严重影响了服务器网络状况,只有千日做贼,没有千日防贼的道理。

因此,从社会工程学的角度,不仅仅要防范,还要主动出击,增加难度。

主要策略

  1. 加入延时,让他采集难度增加,效率下降,如每天100万采集,把响应时间从0.1s延长到5s,那么就可以减少98%的访问,同样的时间内,恶意爬虫一天仅能采集2万;
  2. 适当返回正确状态的假数据、垃圾内容、扰乱他们正常采集,让他们花大量时间在正确内容的甄别上;
  3. 通过跳转的形式,把爬虫的攻击引回他自己的服务器、竞争对手的网站;
  4. 通过跳转的形式,让爬虫去下载大容量 iso 文件(国内各大镜像),搞挂他的内存、数据库;
  5. 返回一些包含恶意js、非标准的html内容,搞坏他们的爬虫分析,及时中止对方程序;
  6. 必要时,可以使用杀手锏,跳转到当地公安局、境外安全组织、黑客组织。