backslash r

一直都知道Windows底下的换行符是 \r\n,Linux系统下是\n
但并没有关心过 \r\n 到底是什么意思。其实 \r 是将光标移至行首,而 \n 是将光标移至下一行。这么一看也理解了为什么Windows会将换行符设置为\r\n了。

下面这段代码,可以看出\r的作用。

1
2
3
4
5
6
7
8
9
10
var i = 0
function update() {
i++
process.stdout.write("\r" + i)
if ((i % 10) == 0) {
console.log("")
}
}
setInterval(update, 100)

我在热拉工作的体验

两年前我以CTO身份加入了一家专注于拉拉社交的互联网公司——热拉。有次和一个身在国外的朋友提起我正在做LGBT,他的第一反应是,wow!so cool!要知道,在硅谷,库克等一帮大佬都是弯的,数据显示硅谷有三分之一公司的中高层都是同性恋。所以在他人眼中,从事LGBT是一件很fasion的事业。配合我不羁的长发和稀虚的胡渣,很多人认为我也是弯的。很遗憾,我是一个直男癌晚期!

在很多人的看来,一个小众社交软件应该是很简单的,做好它应该不难。起初我也认为自己可以驾轻就熟的做好这件事,并且不需要多少的人手,但我很快意识到没那么简单。在我加入之时,热拉已经是上线了一年多,拥有完整的产品形态,几十万体量的用户。所有后端由java开发,每天到了晚高峰时间,服务器都会崩溃。而与此同时,我们的市场推广依然不能停下,产品迭代仍要进行,这对于技术架构改进来说,无疑是雪上加霜。

我提出了招聘更多的人员,拆分为两个后端团队的想法,一个团队进行产品架构的重构,而另一团队则对现有系统进行维护和改进,在重构完成后切换到新系统上。这个方案很快被否定了,相反,我们需要对团队进行压缩,因为我们当时正面临着财务的压力。原本人员就严重不足的后端团队,减少了一位java工程师,和运维工程师。
我们当时无暇去做架构上的调整,并不是我们不明白它的重要性,而是情势使然。我们只能从运维的角度来进行优化,将现有系统看作一个黑盒的系统,从各项指标来分析整个系统的瓶颈所在,按影响程度从高到低进行优化。至少,在晚高峰的时候服务器不再频繁的崩溃了。

为了在进行现有系统优化的同时,依然能满足产品迭代的需求,我尽可能的不增加现有后台的负担,使用node.js 提供完全独立于现有系统的一部分新API接口。选择node.js是因为他的开发效率高,也可以保证与现有系统完全解耦。

在这样的团队结构下,服务逐步得到了稳定,产品也在不断迭代中。虽然过程中我们依然遇到了各种各样的问题,但我们也度过了最困难的时期,成功融资,并且拥有了变现能力,现在的财务状况非常之好。

热拉何时开始引入Go语言的?

在技术选型上编程语言的选型是基础,每种编程语言都有不同的特性,开源社区或是某家大公司支持都会影响它的生态。Java整个生态并不符合我们的“审美”。而且既有的java服务很不稳定,所以我们一直有计划替换掉java。

我们原本考虑使用node.js作为后端主要开发语言,但是我们在人才招聘上遇到了障碍,原因在于node.js工程师的后端能力可以说是良莠不齐。在意识到这一点后,我们决定使用Golang作为后端主要开发语言,而node.js主要应用于web相关的项目中。golang程序员相对而言,编程基础更加扎实,对后端的sense更好。

我们首次尝试Golang,是在聊天系统(IM)中。热拉的IM系统此前是使用的是XMPP协议的开源框架,当时已经达到了性能的瓶颈,难以维护和优化。因为IM系统是相对独立的,重写它对于整个系统架构没有太大影响,所以我决定自己使用Golang做一套IM系统。准确的说我们所开发的是一套网络通信框架,它包含Go服务端框架、Go客户端库、iOS客户端库、Android客户端库。我们的IM系统就是在这套网络通信框架之上开发的,目前已经在线上稳定运行一年多了。

另一个Golang的使用是重写整个后端API。当时我们的用户相比之前已经翻了几番,除了IM之外的功能主要还是在老后台上,在经历了几次严重的故障之后,我们终于决定使用Golang重写。我们的目标是灰度的、无缝的迁移,一切的重写对用户来说都是无感知的。所以Golang在热拉技术架构中的比重也越来越大了

介绍一下技术团队

热拉这个产品除了在用户量级上比其他社交软件小以外,在产品功能上一点也不比其他社交软件少,甚至还要更多,更复杂。对比我们的团队规模,还是非常有挑战的,我们的原则是“小而美”。对于一名程序员来说,还有什么比做一件充满挑战的事情更有趣的呢?

我们下一步的计划是按照微服务架构对服务进行重构,这次是重构而不是重写。你可能会好奇,为什么不直接使用Golang重构,而是先重写,再重构?这一点说来话长,简言之是权衡风险与成本的结果。

我们认为每个微服务模块都应该有唯一的负责人,这可以让每一个团队成员都有自主发挥的空间。一部分的微服务也成为了我们实验新技术的环境,consul,NSQ等技术都有在应用。我们也会在接下来组建数据团队,在大数据架构中依然会选择Golang作为主要的语言,这与很多公司以java为主的做法是不一样的,但我们相信Golang是可以胜任大数据基础架构的工作的,并且可以让我们使用更少的人力资源和硬件资源来完成这件事。当然,这也是一个新的挑战。

所以我们也在 招聘更多优秀的Golang程序员

  • 我们希望你首先对于Golang 语言特性的理解上是扎实的,同时也有3年以上的任意编程语言的后端开发经验
  • 如果你完全没有Golang的经验,但是后端经验非常丰富,并乐于转型到Golang,我们也非常欢迎
  • 如果你在github上有开源项目,在stackoverflow上有贡献答案,有坚持写博客的习惯,请把链接甩给我们
  • 如果你有大数据相关经验那就更合适了
  • 我们鼓励交流和分享,但不鼓励加班,我们认为加班与工作效率不存在正相关性
  • MBP是标配,也可以配备外置显示器

如果你对我们有兴趣,请将你的简历直接发送至我的邮箱: leen@thel.co

创作共用协议

作为缺乏审美的工程师,当想要独立设计一些页面时,有时会感到力不从心。所幸的是如今是一个知识共享的时代,在码农的圈子里有开放源代码协议,在设计的圈子里也有创作共用协议即Creative Commons协议。

比如我们所熟知的bootstrap,其代码是使用MIT协议发布的,而其官网则是以Creative Commons协议发布的,意味着我们可以在CC协议之下使用其官网的设计。

有许多的设计开始通过Creative Commons协议发布,包括网页设计、字体、图标集等。

其他一些非CC协议的免费设计资源

  • mononoki 字体

我今天都干了啥?

我今天都干了啥

今天起了个大早,送娃上学,回来还早,玩了局王者,吃早饭,上班

打开电脑看了下TODO,邮箱、微信、QQ上的很多未读消息。

11点面试了一位产品经理,聊了她的工作经历,以及她对产品的理解,抛出了一些问题,没有什么问题,但也没有什么亮点打动我,还是淘汰了。

年后对接了很多三方服务,合同流程要走。两家文本识别服务,我们需要评估其质量,安排小伙伴将差异数据整理,并安排人工复审,统计各家质量,督促改进。

抽烟的时候,使用我们的app发了一个话题。

安排团建小分队的同学,确定技术分享会的最终流程,奖品,准备全员邮件,确认邮件内容。

准备新的JD,招人,也要看一下新的人才招聘渠道,与HR沟通。

叫外卖,吃午饭,今天没玩王者。休息一下,听公开课午睡。

某CDN的合作协议,来回多次,无法接受,对方的售前沟通能力实在够呛,也说明他们的服务的确一般,无奈国内网络环境就这样,而他们价格尚可接受,只得继续纠缠。

某些提现操作失败,需要退回金额,这个操作比较敏感,我一直是手动操作。决定安排小伙伴优化这段代码,完全自动化。

另一个必须手动操作的金额相关的调整。

某SEO合同寄到,签字盖章安排寄回,通知对方。

某直播服务合同确认,一些技术和计费细节还是要沟通清楚。我真的很努力的在为公司省钱啊。

某直播账单发票寄到,向财务请款,提醒相关人员审批。

某发邮件服务余额不足,前去支付并申请发票,以便以后报销。

还有一堆简历没有筛选,质量太差,懒得筛选。

开始写这个记录,回忆一下一天都干了什么。

开了一个10分钟的小会。

大部分的沟通都是需要往复的,所以以上很多事情都没有真正结束。我需要重新看一下TODO,整理一下思路。

已经周三了,本周计划还没提交,前去整理提交。

今天中途抽了几根烟,继续看那本关于人性的书。

产生了一个产品灵感,记录一下,年纪越大灵感越少,要珍惜。

已经17:30了,还有时间,要把简历都筛选掉。

感谢我的小伙伴们,没有什么事来打扰我,所以说团队搭建是CTO的首要工作。我也是心大,对他们的工作很放心,其实我最应该做的就是review一下他们的工作。说实话,我挺怀念不闻窗外事,只管写代码的日子,心静!那种不断的思考、设计、实现的过程,很爽。而现在不得不处理各种事情,没什么难度,但也不能假手于人。

可能是年初吧,各种外部的、产品的、团队的事情都挤在了一起,希望可以尽快了解掉一些事情,让自己可以更专注在某一方面。

公共画像

什么是SNS的本质?当我们看待一个SNS的时候,我们看到的是什么?

信息、状态、转发、私信、粉丝、评论,我们看到的是这些产品功能吗?还是这些数据?他的价值在哪里?

一个SNS,我们看到的是,我们自己的公共形象,或者是某些人的公共形象。SNS为这些红人提供了舞台。

而且,每个SNS所提供的舞台是不一样的,往来的红人也是不一样的。

SNS就像一个主题酒吧,来往形形色色的人,但他们身上或多或少会有一些共同点。在同一个SNS上,他们有同样的期许。

粉丝是一个两难的设计。没有粉丝,红人们没有动力在SNS上奋斗,而有了粉丝之后,任何的SNS最终会走向固化,红人霸占了主要的SNS资源。

这也是各种SNS会不断推陈出新的原因,因为有一批有潜质的红人,无论他/她是什么类别的红人,他需要一个舞台。但是有些场子,已经被人霸占,于是他们不得不寻找新的舞台。而总有一些SNS平台会抓住一些机会,提供某个类别的小舞台,这就是垂直SNS。

是否有可能干翻霸主级的社交网络?Facebook,twitter,国内的腾讯、微博。答案是能!本质上腾讯就被自己干翻了,微信取代QQ,本质上就是对霸主的挑战,虽然这一切发生在腾讯内部。但是微信取代QQ,这样的现象是难以复制的,为什么呢?因为微信取代QQ是发生在移动互联网与传统互联网更替的阶段的,是大事因缘,没有微信取代QQ,也会有其他应用取代QQ,但机会只有一次。

陌陌,用陌生人社交的方式占领了一定的市场,但是陌陌本身的名称定位已经把自己钉死了,就是陌生人社交。微信早期用摇一摇也达到了同样的爆发式增长,但用户规模上去之后,微信就可以弱化了这一个功能。

SNS下一个风口在哪里?SNS不是风口,但机会永远存在。挑战霸主级的社交网络,需要的是天时地利人和。产品与用户,双方共同成就了一个霸主级社交产品。得红人者得天下,微博的发展正是这样的模式。

但红人是本身就存在的,还是通过平台而红的,这个问题很关键。一个优秀的SNS平台应该有制造红人的能力,或者是让红人可以成长起来的能力。当你知道的红人越来越多的来自微信公众号,而不是来自微博的时候,那么说明微博的影响力降低了。

因此霸主级的似乎不可撼动的庞然大物其实是可以被打败的。

如何再造一个现象级的社交网络,我们不应该从产品模式上来思考这个问题,而是需要从人性的角度上来思考这个问题。人性是社交网络之所以成立的本质。更具体的说,人的社会性,情绪化,是社交网络的根本驱动力。人渴望被关注,渴望交流,渴望存在感,或只是渴望来自他人的声音。找到人在精神上的未被充分满足的需求点,强化这种概念,就有机会在社交产品中找到一席之地。

Python数据分析笔记

[可选]

install python

1
2
3
4
pip install -U pip
pip install <something>
pip uninstall <something>

pip support virtualenv

[Anaconda]

Install anaconda

国内可从清华镜像下载,并设置镜像

清华镜像源

MacOS:

1
2
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda2-x.x.x-MacOSX-x86_64.sh`
bash Anaconda2-x.x.x-MacOS-x86_64.sh

会安装到~/anaconda2下,默认会将PATH设置在 bash_profile中,根据你自己的shell设置,加入

1
export PATH="/home/xx/anaconda2/bin:$PATH"

重新打开你的shell,执行conda命令测试。

1
2
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes

Python环境管理:

1
2
conda create --name py27 python=2.7
activate py27

包管理:

1
2
conda list
conda install numpy

(conda install 会安装或更新依赖库,pip install则不会)

[安装工具包]

conda install numpy scipy pandas matplotlib

[IDE]

spyder, pycharm, sublime text, vim

[Jupyter]

ipython 一个更好的python交互命令

jupyter notebook Web记事本,可以将交互过程记录并分享。

后续使用 jupyter 记录。

问题汇总

负责某公司技术以来,遇到了一些问题,汇总一下:

  1. 接口设计问题,错误的接口设计将导致难以避免的问题
  2. DNS劫持问题,用户网络问题定位困难
  3. 苹果IAP漏单问题
  4. 缓存时间、状态不一致、压力太大、崩溃重启、启动慢问题
  5. NoSQL选型问题
  6. 数据库负载问题,主从同步问题
  7. 日志监控问题
  8. 服务自动扩容,全球部署问题
  9. 垃圾信息、僵尸账号问题
  10. IM丢消息,收不到消息问题。
  11. IM、群聊问题定位、测试困难
  12. 聊天信息存储问题

笔墨之殇

说点什么好呢?这两天我开始,翻阅以前我读过的书,我发现,有很多的书,只是草草看过,还有一些书,根本没有看过。原来自己有做读书笔记的习惯,可是当我把阅读的时间放到地铁上之后,这个习惯,也随之消失了。以至于我根本不知道这本书,有没有读过。纸质书,可以有记录笔记的空间,而电子书,阅读起来比较方便,我想这就是纸质书和电子书的区别吧!

以前我总想写点文字。可是我发现自己,写作的速度越来越慢了,也找不到合适的输入法。拼音输入法,当你想打一些,书面语,或者是文言文的时候,就很难输入。而,五笔输入法或者其他的字型输入法,都有一个问题,就是,学起来太麻烦了,我根本记不住那些字码表,而且,当我,去回忆那些字码的时候,我的思路已经被打断了。

我还是喜欢拿着笔在纸上写字的感觉。在这种状态下,我的思路是最流畅的。

一直以来,我都想写一两本小说,可是构思了很久,却迟迟没有动笔。自己内心真正想表达的东西,和整个故事的结构,往往存在冲突。我不愿意写一些,没有人想看的东西,但我也不想,完全是为了迎合别人的口味,而写作。

其实,这并不是什么文章,我这是在测试一种新的输入法,一种,新的写作方式,那就是,直接把我想写的,念出来。你所看到的一切,都是我通过语音输入的。好吧,今天就说到这里,我的脚也泡好了。

如何学习编程

编程入门

大部分人都是通过某一个原因,喜欢上了编程。同样,你也需要一个理由。也许只是走在路上,忽然有人对你说:“年轻人,我看你天赋异禀,骨骼惊奇,我这里有一套编程秘笈,你想不想学啊”

入门编程语言,有很多选择,你可以选择python、JS,也可以选择C。比如我自己,是通过Basic语言入门的,也是因为它喜欢上了编程。

在这一阶段,最容易出现的问题是:Compiler Error,Syntax Error。你还不习惯和计算机进行沟通,你们之间的语言不够顺畅。它听不懂你说什么,当它说Error,你也听不懂它在说什么。你总是很抓狂的问,What’s the Error,一定是计算机出了什么问题,而不是我的代码有任何问题。直到你意识到,计算机没有任何问题,有问题的一定是我的代码,你能够检查你的代码,修复语法错误,恭喜你,你已经入门了。

这一阶段,你对编程有了感性的认识。你为自己写出来的东西感到骄傲,完全不会注意到其实那些代码其实只是piece of shit。你也会遇到很多的问题,即使你已经查阅到了所需要的知识点,还是无法实现你要的功能。就好像已经把所需要的材料全部交给了你,你却无法用这些材料造出你想造的东西。

这一段时间,你的灵感泉涌,有很多的想法想要去做,但却又感觉力不从心。你需要开始补充一些基础知识了,难度也要开始增加。

计算机科学基础

这是一个非常重要的阶段,这一阶段的学习效果,直接决定了你的技术实力。有些知识,并不会立刻用得上,但是,这些知识,已经潜移默化的影响了你的思维方式。你的任督二脉将在这一阶段打开。

算法

算法和数据结构 这是一切程序的基础,你需要恰当的使用这些数据结构,你无法绕开它们。有一些算法,你需要知道它们的原理,这有助于你理解你的代码最终在计算机上是如何运行的。你可能并不需要掌握算法设计的机巧,也不需要去参加一个算法比赛。但你需要理解这些经典算法,记住它们的名字,在你遇到问题时,第一时间想到它们。最终,你可能不需要自己去实现它们,但你需要恰当的使用现有的算法代码。

设计模式

函数式编程、面向对象编程,设计模式。这些方面的知识,你也需要掌握,你需要了解如何将自己的代码组织在一起。这就像你拥有了一些积木,你需要了解玩积木的常用技巧。阅读一些书籍或者阅读他人的代码,都是非常好的途径。学习这些知识,就像是学习作画。这些技巧你一看就会明白,但却不能熟练的使用。这里是考验你艺术天分的地方。

在拥有了以上这些技能后,你已经可以算是一个不错的程序员了。但这些知识可以让你写出很棒的代码,却无法使你的程序有任何的功能。你必须要让你的程序和外界进行交互,它才有存在的价值。

运行环境

你的程序如何和外界进行交互?你的程序是运行在一个封闭的环境之中的。想象一下,一只猴子被关进了一个房间中,房间中有一个操作面板,当它按下某个按钮,外界就会发生某件事情,比如说在你的电脑上打开一个新网页。你的程序就是这只猴子,你必须熟悉你的操作面板,有些时候面对一些奇怪的面板故障,你甚至需要了解它的工作原理,以避免发生那些故障。

网络基础, TCP/IP 协议,HTTP协议,如果你要开发网络应用,这些都是非常重要的基础知识。

操作系统原理,无论你开发桌面应用、移动应用、嵌入式应用、网络应用、服务器端应用,你都应该对你的程序所运行的环境有足够了解。

如果你开发的是Web应用,也许你不需要了解操作系统,但你需要了解你的浏览器,它是你的运行环境。

计算机架构,这个你可以不必知道。但如果你要开发一个操作系统,那么你必须对计算机架构有所了解,还是那句话,你需要了解你的程序所运行的环境。而操作系统所运行的环境就是计算机硬件的体系架构。

交流

你需要一个目标,你定下的这个目标可能就是下一个facebook。带着目标学习,这是我所推崇的方式。对于还处于学习阶段的你来说,这是一段幸福的时光。你不必为了生计而学习,你可以纯粹的为了爱好而学习。

你需要加入开发者交流的社区,加入论坛、QQ群、讨论组、邮件列表。与别人分享你的收获与挫折,社区的氛围也是你继续学习的动力之一。当你遇到难题,可以在社区里提问。但是你应该学习一些提问的智慧,不要做伸手党,这对你的学习不会有任何帮助。你应该至少已经阅读了相关的书籍、资料,并借助搜索引擎(不要使用baidu,中国可以用bing)来寻求答案。记住一点:社区不能给你想要的东西,但社区可以解答你的疑惑。社区是用来交流的,你也可以通过回答别人的问题来提高自己的知识。

开源社区,也是你获取知识技能的主要来源之一。当你需要某个功能,有人可能已经实现了他,并将他开源在了github(目前最大的开源社区)之类的地方。这些开源项目可以帮助你解决某些细节问题,使你可以更专注在你的主要目标上。对于优秀的开源项目,你可以阅读他们的代码,学习他们的机巧。

再论运行环境

如果你仔细体会的话,你会发现,编写代码只占到你学习编程中的很少的一部分时间,而大部分时间,你是在查阅资料。你需要花大量的时间在学习程序的运行环境上,而不是学习编程语言上。运行环境会提供给你很多的编程接口,一般被称之为API。

我这里所说的运行环境,并不是仅仅指操作系统运行环境,它也可以是浏览器,Java运行环境,Sevlet容器,node.js,unity3D运行环境,flash运行环境,directX,OpenGL,cocos2d游戏开发框架。

你可能注意到了一点,我将开发框架,视作了一种运行环境。为什么这么说呢?因为框架是对运行环境的再次封装,在框架之上,你将看到更加易用,更加人性化的接口。有一些框架,还额外提供了很多辅助的库,甚至插件机制,让你可以直接使用整个社区贡献的插件。你只需要面对框架编程,借来几个插件,再搭配几个辅助库,就可以完成一个作品。

你明白了吗?编程就是这么简单!这也是为什么有那么多平庸的程序员的主要原因————他们只懂得在框架之上编程,使用别人写好的现成的代码。可是一旦他所赖以生存的框架或插件或库,出现了任何问题,他们的平庸就会显现

如果你是初次接触编程,还不知道什么是开发框架(framework)什么是库(library)的话,没关系,你只需要记住一点:Library决定了你能做什么,framework决定了你不能做什么。如果有一个新的框架,让你眼前一亮,蠢蠢欲动,请保持冷静,先想一想,如果你用了这个框架,你将失去哪些能力,是否是可以接受的?我看过太多的项目因为框架的限制,而不得不使用一些旁门左道来突破框架的限制,从而失去了代码的美感。抑或是自己动手,将框架改的面目全非,完全失去了框架的意义。

对于初学者,我强烈建议远离框架。框架是一种捷径,但对于一个以学习阶段的人来说,捷径是并不是什么好事。如果你已经有了足够的经验,对你的运行环境足够了解了之后,你应该在你的运行环境之上,寻找一个优秀的框架,学习它的设计思想。更进一步的,你可以搭建一个你自己的框架。我并不反对使用框架,但我反对不求甚解的使用框架。

修炼是一个长期的过程,即使你已经成为了一名优秀的程序员,你依然需要不断的修炼。记住一点:修炼的捷径就是不走捷径

Hack

你可能想要做一些看起来不可能的事情,这通常是从某个夸张的想法而引起的。Hook、反射,这些略有些高级的技巧。

软件工程

你已经找到了你的第一份工作,你加入了一个团队,经过一段时间,你又被提升为了项目组长。你需要开始考虑一些团队管理问题、系统架构问题

专业方向

一些资源:

MIT 6.828 操作系统工程
github.com
stackshare.io
stackoverflow.com