proxy_next_upstream 对POST无效

需要添加non_idemponent,官方文档的说明是:
normally, requests with a non-idempotent method (POST, LOCK, PATCH) are not passed to the next server if a request has been sent to an upstream server (1.9.13); enabling this option explicitly allows retrying such requests;
意思是如果不加上non_idemponent,对POST这些不幂等的方法,出错是不会重试的。

猜测

按照严格RESTful设计,PUT和POST都是对资源的修改,比如新增一个用户、修改某个信息、增加积分等等。GET请求一般用于查询资源的情况,一般情况下都是幂等的,意味着不管执行多少次,结果都是一样的。当遇到5xx的时候,POST的请求如果没有使用事务,可能结束了,也可能没有结束,即便用了事务,也可能一定的几率会执行成功了,但没有正确返回。POST如果是用来新增一些资源,proxy_next_upstream可能会导致出现一些业务逻辑上的异常。
但很多场景下,出于加密或者其他考虑(如:前端不好支持等等),有些业务并不是按照严格的RESTful来实现的,如果后端做了一些充分的容错处理,支持接口幂等。那么是可以对POST等接口做一个失败重试,相应的配置要加上non_idemponent,就会生效。

爬虫的抓取错误

前言

一个网站在处理百度爬虫抓取情况的时候,遇到了大量的抓取错误,记录一下解决问题的过程和思路。
百度的解释是当百度spider访问服务器,进行tcp通信的时候,socket读写发生异常,导致数据不能正常返回。请检查服务器连接状况和防火墙设置是否符合预期
首先列出该网站的特征信息:香港机房,HTTPS请求,后端server为nginx。
先通过另外的域名,位于广州机房的网站,抓取若干次,发现还是偶发socket错误,同时将香港机房的请求由https改为http,抓取50次没有任何问题。故可以得出结论一:

  1. 不是因为机房位置问题导致的,而是因为HTTPS引起的,而具体是因为server配置不正确,还是受到GFW等干扰而引起的,不得而知。(内心os:某网站爬虫真垃圾)
    根据结论一,可以得出一个兜底策略,可以不用https,直接改用http,别搞这些幺蛾子了。

深入分析

本着继续挖掘https引起的问题,故还是深入研究一下问题所在。
首先怀疑Cipher suites与ocsp等问题,把这些安全配置逐个去掉,发现没有起到作用,还是有错误。
尝试过千万种可能之后,都开始怀疑人生了,最终得出一个结论,只有可能是百度爬虫自己的问题。于是把服务器的server直接关掉,抓取几次应该是得到443 Connection refused,但通过百度爬虫抓取,还是得到了socket 读写错误。(我服务器都关掉了,还是有这个错误,这只有可能是百度自己的错误了)
本以为能发现什么大的问题,找到服务器有什么常年存在的错误,结果是这个原因。

Vagrant 如何压缩空间

Vagrant

vagrant是个很好用的工具,可以用来工作流构建和管理虚拟机环境,常用的命令也很简单易用,可以配合VirtualBox来启动各类的虚拟机,简单易用。vagrant主要是负责镜像的管理,尤其是对于Mac系统来说,虚拟机比起Docker Desktop或者brew要更加方便管理、迁移、分享,可以更专注于linux做好事情,减少系统差异。另一个场景是当一个线上环境需要安装大量的依赖,如何对新人更加友好,如何使得所有的变更都能迅速同步给所有同学,vagrant也可以用于多环境的情况。
可以养成定期备份快照的好习惯,如果某些文件被误删,或者需要回滚一些操作的时候,就非常方便了。

如何压缩空间

随着使用时间的增长,vagrant的容器体积会不断变大,有一天可能会把宿主机的磁盘都占满。vagrant的容器类似docker,我认为他应该是会不断叠加层级,因为从观察来看,新建一个文件,再删除掉这个文件,镜像的大小并没有减少。他会有一些空间回收,但往往不是那么及时,那么从使用者的角度来说,如何让他更快回收空间,并且确保镜像尽可能小呢。
我罗列出我常用的几个步骤,其中//为注释的说明内容。

1
2
3
4
5
6
7
8
9
// 虚拟机内执行
// 清除所有的没用docker

docker system prune --volumes -a
// 对镜像做磁盘空间擦除

sudo dd if=/dev/zero of=/EMPTY bs=1M
sudo rm -f /EMPTY
// 宿主机执行
// 打包镜像

vagrant package --output package.box.20200214

这时候,已经压缩好的镜像就生成好了,也可以将该box分享给其他同学,作为一个内部测试环境等等。
把原虚拟机销毁(vagrant destory,不熟练的话,请谨慎使用),然后修改Vagrantfile,将文件名修改为刚刚打包好的box,通过vagrant up,虚拟机就又重新焕发新生了。

写在2020年代的开篇

2020年1月28日,2019-nCoV还在持续爆发与扩散,中国国务院延长了假期,阿富汗塔利班击落了美国CIA的客机(美国军方表示质疑),众多错综复杂的消息也预示着,2020年将是一个不平凡的一年。不平凡的一年,这句话套用到任何年份都可以,就像基金经理人总要在年终总结的时候,告诉所有投资人,他今年做了哪些正确的决定,帮助大家创造了多大的效益。

成长,过去一年学到的知识

拥抱不确定

学会拥抱不确定性,不确定性过去有、现在有、将来还会有,过去面对不确定性,我总是想着去避免,去对冲,君子不立于危墙之下,就是这个道理。但另一个道理又告诉我们,富贵险中求,人生得意须尽欢。不确定性中往往蕴含着机遇,如果一味消极对待,其实不利于我们个人或者财富增长。反而面对不确定性,应该更加积极、主动。说不定能有一番作为呢。

更加乐观、主动

无论悲观还是乐观,生活总是要继续的,不能说因为我悲观,接下来的日子我就不过了。既然悲观和乐观的结果都是一样的,那么何不乐观一点,至少自己可以开心一点。面对再大的困难和不确定性,可以做好最坏的准备,但要乐观应对。

用长期预测抵御短期预测风险

2019年,如果你在年初买入沪深300,到了年末卖出,她能赚40%以上。而多少聪明的基金管理人、分析师,都远远达不到这个收益,因为短期的预测会让他们认为沪深300已经高估了,到达了卖出点了。在证券市场中,把时间拉长看,现在永远都是低点。在漫漫人生路上,把时间拉长,现在永远都是起点。
短期预期其实往往会不准确,因为干扰因素太大了,就像我们很难预测下周一天气怎么样,温度如何,我参加考试能不能通过。但如果把时间拉长,一个地方的温度,晴天数量和阴天数量是确定的,只要我减持考试,是一定会通过的,只是时间长短问题。股市是一定会涨的,只要你买了,不放弃,终有一日他会给你意想不到的回报。
所有的分析师中,最受欢迎的永远都是那些看涨的,如果涨了,说明他预测对了,如果不涨甚至跌了,至少他给了你安慰,给了你信心。反而是那些看跌的分析师,真的跌了,大部分人可能并不会感激他。
你的预期差,实现必然就差,反而不如对未来客观一点,最坏的可能你都想到了,还能再差到哪里呢?

未来,多一些思考

我想,我等,我期待,未来却不能因此安排。我遇见谁,会有怎样的对白,我等的人,他在多远的未来。
这是孙燕姿的遇见,面向2020年代,我们得明确自己想要达成什么目标,想成为一个怎样的人。现在就要开始着手准备应对下一个10年了。
TODO…

回顾与展望 2020

展望2020

这一年,看书还是没有看多少,去图书馆的次数还是下降了,背英语单词还是依旧只坚持了一小段时间,早睡早起也没有形成习惯。
这一年,还是继续贯彻了极简生活的理念,丢弃了很多不是必须的物品。
这一年,去了杨千嬅演唱会,去了很多地方旅游,去了香港多次露营与游玩。
这一年,离开了广告行业,重新出发。

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

2020计划

家庭生活计划

  • 周三美食日
  • 周六活动日
  • 周日学习日

活动日:执行旅游计划中的短期任务、爬山、远足,因不可抗力可调整为其他积极向上的活动)
学习日:看书、学习

娱乐休闲计划

  • 日本旅游
  • 深圳游玩
  • 香港游玩
  • 澳门游玩
  • 短期旅游

每日时间表

  • 早睡早起,早起运动,早起喝一杯白开水
  • 每天一杯牛奶,吃早餐
  • 每天下午茶
  • 早晚刷牙洗脸洗澡洗头
  • 定期(每月两次)执行超市采购计划,保证家里任何时候都有吃的

财富增长计划

  • 扩大港股持股比例(目前20%,争取一年内扩大至50%)
  • 建立长效投资与长期投资策略(通过ETF+个股+低估行业股,盈利5%以上方可卖出)
  • 扩大可转债投入(尝试增持部分可转债)
  • 继续申购新股
  • 研究新的盈利渠道(含技术相关与非技术相关)

行为习惯提升计划

  • 不断跳出心理舒适区
  • 多聆听,多接纳多方意见
  • 多赞扬肯定对方
  • 严格要求自己,对他人要多宽容
  • 态度要温和
  • 增加对未来10年的思考,明确自己想要达成什么目标,想成为一个怎样的人

每周细分计划

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

2019计划与总结

总结语

过去的2019年,各项计划完成的还不错,实现了一定程度的自我提升,希望再接再厉。

家庭生活计划

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

娱乐休闲计划

  • 日本旅游 ×
  • 深圳游玩 × (去了,但不是游玩)
  • 香港游玩 ✓
  • 澳门游玩 ✓
  • 短期旅游 ✓ (广西南宁、湖南郴州、四川成都与峨眉山、湖南长沙、湖北武汉)

每日时间表

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

财富增长计划

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

行为习惯提升计划

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

体重增长计划

  • 定期执行超市采购计划,保证家里任何时候都有吃的 ✓ (70%)
  • 每天下午增加一个下午茶 ✓ (50%)
  • 要多吃,辅助定期运动 ✓ (已完成体重目标,60KG)

每周细分计划

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

Go的CICD、Module、构建、测试

前言

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

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

基本概念

CI的全称是Continuous Integration,表示持续集成。
在常见的开发场景中,开发人员可能会频繁地提交自己的代码,这些提交的代码,先通过提交Merge Request,再经过Code Review合并到主分支,最终经过测试、灰度,然后上线。
CI主要作用是保障Code Review之前的代码,通过一系列自动化测试验证代码的质量和Bug,提升代码质量,并根据测试结果,向开发人员或团队进行预警。
CI同时也会检查Merge之后的代码是否正常,符合一切预期。

CI的好处

减少Review代码同学的压力与工作量

假若有一个同学经常写bug,他的代码每次都能测出一大堆问题,他自己也没有意识主动去检查自己的代码能不能跑起来,全靠你帮他发现,有些变量名写错了又不好发现。你每次提醒他,他都能快速意识到自己的问题,但下次还是可能会遇到。你作为负责Review代码的同事,面对大量的改动,是否有些担心?

制定并维护团队代码规范

你是一个技术管理,你为团队制定了一系列规范,如上线前自测、各个模块要有相应的设计与说明文档、数据库的DDL变更要及时维护在代码库中、代码的测试用例覆盖率要达到50%。经过一段时间,你发现这些问题并没有很好的改善,如何能够让一起定下规范严格执行呢?

快速迭代,小步快跑

在开发过程中,当你需要改到一些你不是非常熟悉的模块,总担心自己会不会改错一些逻辑,当初写这个逻辑的同学可能也不在了,那么如何确保自己修改的内容有效呢?产品经理又催得紧要求今晚上线?

持续改进与提升

在开发中,你写了一个模块,当时是有较高的QPS,有正常的结果返回,结果随着项目的迭代,你发现该模块变得越来越慢。你发现当初大家约定的Code Style,慢慢也开始变样了,一个方法里面有多种实现,怎么办?

怎么做

CI可以代码库设置了一个较高的标准,所有不符合规范,有语法错误的代码,都可以直接拒绝合并至主分支。
根据不同语言,可以检查语法错误、变量定义但未使用、重复引入package、未格式化、scheme定义不正确、测试用例等等。

  • 代码提交之后,将会根据分支进行不同的自动化处理:
    • 代码常规检查(Code Style、代码底层实现Code Lint等,检测所有语法错误、告警、未使用代码等)
    • 自动化单元测试(输出结果与测试覆盖率,对代码逻辑检测)
    • 复杂用例覆盖测试(构造MySQL、Redis等数据,对业务逻辑检测)
  • 代码Review阶段,由于上一阶段已经对代码质量做了基本检查,相关reviewer只需要review逻辑和实现方案即可。
  • 合并待发布阶段,会自动检查是否冲突,没有冲突自动合并,有冲突则通知相关同学人工介入进行git rebase等处理。
  • 构建阶段,CI可以根据Dockerfile自动构建并将分支推送至镜像仓库。
  • 部署阶段,发布到测试环境、预发环境、线上环境,灰度上线等。

根据上述的过程,我们其实已经将各类简单的脚本变成了一系列自动化执行的流程,也带来了标准化,可以直接一键应用到所有的项目。这就是持续集成,在我们背后无声无息的进行着,减少了大量极其浪费资源的人工执行,对研发团队来说,解决了大量的资源,对研发同学来说,可以减少review代码、测试的时间,也可以更加自信上线,快速迭代,更加专注产品、业务打磨。

在研发流程中,每个人只需要关注自己开发的功能,并编写测试用例来确保自己的功能(逻辑)不受其他人提交的代码影响,同时确保自己没有影响到别人功能(逻辑),其他代码质量、逻辑检验由CI完成。

Gitlab Runner

Gitlab其实是能够关联一些很好的工具,比如一些需求管理、Wiki等等。其中Gitlab CI可以做一些代码检查、跑测试用例、自动构建等等工作。我们使用的代码仓库也是Gitlab,那么使用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,根据项目的特性来编写一些定制化的检查。如if-not-present等配置可以在docker不存在的时候,才拉取相关分支。

镜像构建

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
FROM golang:1.13 as build-env
WORKDIR /go/src/y.cn/some
COPY go.mod ./
RUN GO111MODULE=on go mod download
FROM golang:1.13
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/ ./

最近一些感想

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

技术的价值

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

对海外市场看法

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

回顾与展望 2019

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集美剧