工作大概就定了Ucloud了,前几天已经拿到了公司寄回来的三方,论文快写完了,不出意外的话,毕业应该也没问题了。

这一篇大概写一下为什么选择UCloud,不是毕业生择业指南,只是记录一下,以后在UCloud混的好或者不好,都可以回忆起来现在的我为什么做的这个选择。

几年之前,老哥就说,“你要想好以后要做什么工作,计算机领域这么广,早点选择自己喜欢的领域”。所以我就搞了几年的php,搞了几年的前端,搞了几年的Java,还顺带是半个运维。到找工作的时候,我投的都是Java的后台开发,PHP投都不想投,然后前端,虽然我喜欢玩点前端的东西,但是

“前端是不可能去做前端的,这辈子都不可能去做前端的,数据挖掘又不会。。。额,就是,就得后台这种东西,才能维持的了找到一份工作这样子”
窃·找工作·瓦拉

幸好几年时间也没完全白费,多少还是学了点东西,勉强也拿了几个Offer,其实在所有的Offer里面,UCloud的待遇是最低的(当然差的也不多),为什么选择UCloud呢?

首先,这是一个我很喜欢的行业,云计算。我大三的时候买的第一台服务器,是西部数据(不是卖硬盘的那个)的,其实就是个几百M的虚拟空间加个数据库,卖好几百一年;后来阿里云,AWS也都玩了一年的样子,还买过国外的一个VPS也就几百块,也算对SP略有了解。后来在掌游实习的时候,和运维的胖子关系也挺好,经常请教他一些服务器的东西,掌游用了阿里云和腾讯云的服务器,总的来说为运维节省了很多工作,但是就算阿里云这样的也经常出问题,导致运维经常发朋友圈抨击阿里云的技术。

了解运维的人都知道管理几十台上百台机器是一件非常非常麻烦的事情,部署、维护、升级、迁移、备份、恢复,随便一件都得花很多时间和精力。如果让我去管理10台实体机,简直想都不敢想。而云计算要做的就是这个市场。AWS已经取得了极大的成功,国内的阿里云、腾讯云也做的很大了,为什么我不去他们家而选择UCloud呢,还不是因为阿里腾讯把我刷了(玩笑)。

我认为云计算是一个足够大的市场,并且这个市场还在扩张的阶段,还有很多潜在的客户可以挖掘,不只是互联网行业的客户,传统行业也有很多的潜在客户,这个后面再说。虽然依托互联网巨头的阿里云、腾讯云占据了不小的市场份额,UCloud这样的云平台也还是有很多机会的,最根本的原因是这个市场足够大,并且是一个足够自由竞争的市场,有一定行业壁垒的市场,这可以保证多家优秀的、有一定体量的云服务商同时存在。

和这几年的APP创业不同,云计算行业的创业对技术和资金都是有很高门槛的,虽然有一些开源的云平台方案,还有基于容器技术的方案,但是就算是基于这两类的创业也是要求不低的,而UCloud这样的IaaS服务商对技术和资金要求则更高了。2012年成立的UCloud发展到现在已经证明了自己的实力,在竞争激烈的云计算市场,突破阿里云和腾讯云的压力,能不依靠价格补贴获得现在的市场表现,还维持了不错的口碑,表现了极强的活力,这大概是我选择UCloud的直接原因。

其实在百度实习的时候,就感觉自己可能不是特别适合大公司的环境,大公司有大公司的好处,小公司有小公司的好处,我觉得有选择小公司的魄力也是很重要的。当然UCloud其实不算小公司了,但还是保持了不错的创业公司氛围,希望在UCloud能获得不错的工作体验。

我曾说,找工作呢,也是两厢情愿的事情,不要为了外在的因素而选择某家公司,自己开心最重要。我大概有一个信条就是:如果公司做的东西自己都不会用,不会推荐给周围的人用,那这个Offer就是没有吸引力的。一点资讯是第一个给我Offer的,给钱不少,但是我非常不喜欢今日头条和一点资讯这类的应用,基本不会用它们,偶尔还要喷一下它们,让我去做这个,其实我是有点拒绝的。完美世界给的Offer也还可以,但是是做影视IP游戏化的,完美的面试官真的还挺好的,非常好玩的两个人,可以预想做游戏也挺赚钱的,但是我骂了那么多脑残电视剧和电视剧改编的垃圾游戏,然后我自己去做这样的游戏,估计也会不开心吧。

小米发布mix手机的时候,我说小米如果给我Offer我就去小米做Mix这个“方碑”,当然其实是说着玩的,其实小米给了MIUI的Offer,我虽然是小米的用户,也很支持小米这家公司,但我是不用MIUI的,我大概一直用的CM的系统,还是那句话,自己做的东西如果自己都不会用,那这个工作哪来的激情与乐趣呢?

但是UCloud不一样,我很相信UCloud能提供那种激情,我可以预想去了UCloud,我会放心给之前实习的公司推荐,让他们试用一下UCloud的云服务器,给创业的朋友推荐UCloud。

大概分析一下我现在看到的UCloud的优势与劣势吧。

优势其实比较容易,不错的技术积累,清晰的商业模式,足够稳定的盈利能力,创业公司氛围,技术主导,靠谱的领队人。

我和老哥说我要去UCloud的时候,他回了一个“什么公司?没听说过”,然后估计他去查了一下资料,回了一个“季昕华啊,TK于旸对他评价特别高”。我都没有去了解过季昕华这个人(因为我不太关注安全圈的,因为我觉得安全做的再多,毕竟不是直接有产出的),后来了解了一下季昕华这个人,发现是挺有意思也很强的一个人,业内认为是教父级别的第一代黑客,自称笨极了,人称笨总,据说9年前tk曾评价他“谦和仁厚,识时辨势,临机决断”。我想我会很喜欢这个老板。

云计算这个市场是UCloud最大的优势,UCloud的中立云计算服务商是它区别于阿里云和腾讯云的优势,在国内可以吸引不少中小型公司。虽然AWS和MS Azure等巨头垄断了大部分国外的云计算市场,但是UCloud在国际市场也还是有不少机会的,以现在UCloud做云计算的思路,在国外应该也可以拿到一些市场,但是更多的是需要自身的技术积累。我觉得国际化是必须要走的一条路,主要是进度怎么样决断,太慢了没机会,太快了则拖累整体发展引发风险。竞争激烈的有机会总比没机会好,像微信这样的基本是没有国际化机会的(虽然微信已经很成功了可以不在乎国际化),行业性质决定的,云计算不一样,同样的技术,放到国外也是可行的,可以快速复制的,不会有太多中外差异。相信UCloud有这样的能力和野心。

要说劣势,那就是风险吧,云计算虽然肉大,但是招不住狼多啊,现在做云的公司太多了,不说阿里云腾讯云两个巨头,美团云,金山云,盛大云,百度云,新浪云,随便一个都是有头有脸的牌子,AWS也要全面入华了,Azure在国内的也有些口碑了,竞争不可谓不激烈,好消息是UCloud已经积累了一定的客户,有一定的行业积累,也就是算立足了脚跟了,并且一个竞争激烈的市场说明这是一个有活力的、远未饱和、充满机会的市场;坏消息是还没有办法建立自己的垄断性优势,没有在某个方面的绝对性的领先优势,现在主要的优势是依托于自己的行业敏感性建立的行业服务云,比如深挖游戏行业、直播行业的需求,提供优于其他云的服务。但是这无法建立长久的行业优势,难有优势的聚集效应,别的云也可以依样画葫芦搞一套出来。并且各行业发展迅速,现在金融、教育等行业是云计算的下一个大市场,UCloud如何能保证在游戏行业的优势能在这些行业也继续呢,这是一个比较困难的事情。

尤其是私有云这是一个很大的蛋糕,金融云,政务云这种UCloud要想涉足似乎是比较困难的。我想起之前学校和北京市政府一个单位还有科技部下属一个中心三方合作的项目,系统很简单,但政府花钱不少的(但学校拿到没多少钱),政府单位那机房还时不时重启出问题,这系统弄到云平台,运维成本折半(甚至十分之一都可能)不是问题,政府在IT资源花的钱真的很多,而政务系统云平台化也似乎是一个趋势(虽然短期内似乎不可能),但华为云等公司相比UCloud在这块明显优势大很多,毕竟华为这样的公司和政府谈合作的功力要强太多了。

IaaS之外,PaaS和SaaS都有很大的市场潜力(不过现在还没有特别好的公司能盈利),现在还有BaaS这样的模式,总之云这一块非常精彩,但是UCloud定位为一个中立的云服务商,就不应该在涉足这些行业,在IaaS这一块积累的经验没办法施展,这是一个损失,不过可以将这些行业的公司发展为自己的客户,这是一个可行的策略,不过具体怎么实现很有挑战了。

UCloud大概就这些吧。谈谈岗位,前面说校招投的大部分是Java后台开发,其实我一直对Java后台是不感冒的,所以去玩PHP和Golang也不玩J2EE的。但校招的几个Offer大部分都还是Java后台的,而UCloud给我的感觉不错是给了我一个C++的岗位(有多个岗位可以选),我其实没有学过C++,和部门的人聊的时候说我没学过C++,可能得花点时间补一补,结果人家完全不担心,这种信任我还是很喜欢的。选择一个不熟悉的领域可以带来很多挑战,总是挑战才能让人进步的嘛。我一开始觉得不太可能去做C++的,阿里云内推的时候骁神和我说语言不是问题,还推荐我去做C++,我觉得没学过C++搞不来就选了Java,果然挂了,最后果然还是去做了C++(以后做云还是得向骁神多多学习)。

哦,我曾经选工作的一个想法是,必需有海,也许是因为生长在内陆,然后又在北京呆了6年多,其实对海一直有种小小的执念,上次北京下雨突然想去看海,天真地跑到天津去,才发现天津要看海得再花从北京到天津这么久的时间坐车去海边,然后还是没看到下雨时候的海,Shame。这大概也是我选择上海而不是北京的Offer的原因之一。

当然还有很多其它的原因,就不啰嗦了,先写这么多,有想加的再补充吧。

[update 2016-11-26 16:40]

《Legends of the Fall(燃情岁月)》在IMDB上并不是一部高分电影(7.4),但在豆瓣上排进了Top 200(现在是No.104),在观众中的评价也比较分裂,喜欢的人认为这是一部非常优秀的史诗电影,其对于人内心世界的探索非常深刻;而不喜欢的人则对片中主要角色之间的感情纠葛表示不能接受,不认同其表达的价值观。

先按下三兄弟对一个女人这种比较混乱的爱情不表,这部电影是很优秀的,2个小时讲了一个完整而有深度的故事,加上超一流的配乐(The ludlows),全片掌握有度的节奏,结局的高潮和优秀剪辑,没有毛病。主要的争论在于观众对于电影所要表达的价值观的解读。

首先,我们说《燃情岁月》是一部史诗片,史诗并不一定是它场面宏达,故事宏伟,要讲述英雄人物的历史命运,《燃情岁月》只讲述了20世纪西部草原三个兄弟的故事,但它的时间跨度大,以小见大讲述了这段时间世界价值观念的变化,同时借力印第安人元素探索人物的内心世界。

影片基本讲述了主角三兄弟的一生,很多人看完觉得故事很荒诞,怎么会有这样的人生:三兄弟Alfred, Tristan, Samuel在大草原无忧无虑一起长大,手足之情不用多说,但是老三Samuel的未婚妻的到来让alfred和tristan都内心骚动了(感情大草原只有Susannah一个适龄女青年了?),狗血不,就问你虐不虐。更虐的是,老三一心要去参加一战保卫文明世界,两位大哥陪着去保护老三,结果老三惨死异乡,这就有点尴尬了。先回家的Alfred按耐不住和Susannah说,“虽然 Samuel死了,虽然你不能像爱Samuel一样爱我,但是我们在一起应该能过得很幸福”,这是什么逻辑我是没看懂了。但是女主Susannah其实一开始见到老二Tristan的时候就有点来电,而初见Alfred的时候他们对于改革的思想分歧可以看出Susannah和Alfred不是一个世界的人。Tristan从战场回来之后,和女主迅速走到一起,老大Alfred只能离开家去城市发展。

大概的感情纠葛就是这样,是有那么一点狗血和不现实,但是电影所以这么拍,很多时候并不是只考虑在现实世界可不可能发生,更重要的是创作者想要表达什么样的主题。往大了讲是传统价值观和新世纪价值观的冲突,但这太空洞相当于什么都没说。只看这几个人的感情,大概可以看出来,作品要表现的大概是感情,或者爱情最原始的状态是什么,抛去”文明世界”对于爱情的探索越来越复杂的理性外衣,感情就是荒诞的,对于一个人同时爱上多个人,多个人爱上一个人这种似乎是荒诞的事情,其实没有什么荒诞的了,至甚认为这样很荒诞的文明社会不是更荒诞一些?

感情线来说,Susannah和Alfred结婚了,Alfred成为了国会议员,Tristan回到草原和小Isabel结婚安定下来。看似风光无限,但Susannah终究和Alfred不是一个世界的人,最终剪发后饮弹自杀,而Isabel也因中了流弹而死去。最终最美好的那些人都埋葬在了大草原。

很多人喜欢这个电影是迷上了Tristan的放荡不羁和追求自由的狂野,一味称赞这样的品质,恨不能自己也能像Tristan那样放荡不羁爱自由一回,但是通常画风一转就开始批判Tristan的不负责任。我们是生活在社会中的一员,不可能像Tristan那样不负责任的,虽然Tristan多受神的眷顾,但是他的一生却为他的不羁付出了惨重的代价,包括Susannah的悲剧,Isabel的死。很多人都认为自己的心中也有一头熊,代表自己要追求的野性,代表自己未泯的自由向往,但是他们却很早就没有考虑过自由的代价了,心中的那头熊早已死去了,却一直安慰自己还能追求自由。其实,看起来Tristan是放荡不羁追求自由的,实际上,更多的是也逃避。放不下Samuel的死,负担不了Susannah的爱,有些东西无法承受了,便以自由的名义逃避。现实中这种逃避有的是自杀,有的是抑郁,有的是隐姓埋名,有的是Tristan的离家出走。Tristan回到家的那刻代表他不再逃避了,愿意承担某种责任了,但是物是人非这样的事情总是会发生的,所以就有那么多的悲剧了。

Tristan抛弃Susannah出去“探究内心世界”的时候,Alfred回家正好看到Susannah收到Tristan的信说“all we had is dead as i am dead”那一段,Alfred对Susannah说:“Susannah, you deserve to be happy”。实际上,我们认为那些 deserve to be happy 的人过得并不那么happy。

之前一直使用shadowsocks-qt5的ss客户端,但是最近不知道怎么回事,一启动它过几秒就崩溃,重装也没有效果,只好写两个脚本控制了。

首先需要安装sslocal的包:

sudo dnf install python-pip
sudo pip install shadowsocks

安装了shadowsocks后就可以用 sslocal命令来连接shadowsocks服务器了,还需要一个关闭连接,我们可以使用ps -aux|grep + kill -9 pid 来实现。具体的脚本见下:

启动脚本

启动要考虑关闭之前存在的连接,并且我的sever同时有ipv4和ipv6服务,可通过命令行参数选择连接到ipv6。具体脚本如下:

#! /bin/sh

ip=*7*.***.*7.*7
ip6=2**:f7**:4*:c**::****:****

if [[ $# -eq 1 && $1 -eq 6 ]]; then
ip=$ip6
fi

# close existed sslocal proc
# may need change the path, or add bash to PATH
~/bin/bashes/close-ss
echo "connecting at $ip"
sslocal -s $ip -p 18989 -l 1080 -k password -t 600 -m aes-256-cfb &>>/path/to/log/ss.log &

echo "done with: $?"

在连接脚本中使用了关闭功能,因为对于一个新的连接需要先关闭之前的连接

关闭连接

关闭连接使用ps查找到pid,再调用kill关闭进程,也可以将pid写到一个文件,都差不多,具体如下:

#! /bin/sh
procs=`ps aux|grep sslocal`
count=`echo "$procs"|wc -l`

if [[ count -eq 1 ]]; then
echo "no ss-local runs"
exit;
fi

pid=`echo "$procs"|head -1 |awk '{print $2}'`
echo "closing by pid: $pid"

kill -9 $pid

if [ $? -eq 0 ]; then
echo "result: success"
# clean log file
: > /path/to/log/ss.log
else
echo "fialed to close sslocal"
fi

++ update @2017-02-10 ++
关闭sslocal的时候,之前使用的是ps+grep找出pid,实际上可以用pgrep更快更方便地找出来,更新后的代码如下:

#! /bin/sh
procs=`pgrep sslocal`
if [[ -z $procs ]]; then
echo "no ss-local runs"
exit;
fi

for pid in $procs; do
echo "closing by pid: $pid"
kill -9 $pid
done

if [ $? -eq 0 ]; then
echo "result: success"
: > ~/tmp/ss.log
else
echo "fialed to close sslocal"
fi

可以将两个脚本的目录放到 PATH 里面,分别命名为sssclose-ss,这样就可以通过下面的命令启动和关闭shadowsocks的客户端了:

# 启用默认ipv4连接
sss

# 启用ipv6连接
sss 6

# 关闭连接
close-ss

还是很方便的。

最近忙些什么呢
追了几部剧
新出的《西部世界》是一部科幻剧
大有要超越《权力的游戏》的潜力
权力的游戏到第六季已经显得有点力不从心了
没有了马丁大爷的帮助,编剧在很多地方出现漏洞
尤其是龙母线,已经崩坏得厉害
很多情节都莫名其妙,高庭线,北境线,沙蛇线基本全线崩坏
GOT已经不再是曾经的神剧了,现在看来极有可能烂尾
当然不会像其他剧那样的烂尾,HBO还是能保证基本的水准的
只是相比前三季,没有原著支撑后,水平下降的厉害
而新出的这个西部世界,设定极其宏大,要探讨的问题也很深邃
从第一集的水准来看,具备成为下一部神剧的基础
可以期待一下

另外补了英剧《Black Books》
这个剧之前看过一两集
最近再看,发现非常精彩
经典的英式喜剧,有点 IT 狂人的味道
其实前两周还看了两集TBBT(The Big Bang Thoery),第九季
从第五季后就没追TBBT了
TBBT真的是烂尾的厉害,卖萌耍宝,偶尔还能出一两个段子
但整体水平不行了,赶紧结束这个系列吧
一般来说,很少有超过6季还能保持水准的
Black Books基本能从头笑到尾,三季的长度也很合适
英剧的幽默和美式喜剧还是很大区别的
美式情景喜剧,老友记是巅峰,其实看多了也挺没意思的
最有英式风格的大概是《30 Rock》,但是总觉得那个系列有点恶俗
补完了《Black Books》第一季,有点意思

十一还做了两件事
终于学了一下tmux,这也是一个神器
之前一直想学来着,终于花了一两天系统性地学了一下
之前对于终端复用器的理解一直不太对
这几天都是基于tmux工作,简直不要太舒服,不要太便利!
Nice Tool
喜欢终端的用户一定不能错过tmux
另外还用上了moc,music on commandline
虽然Fedora下网易云音乐也可用,但播放本地音乐的能力有点弱
我还是喜欢本地音乐的,百来G的曲库的样子
moc搭配上tmux操作起来不要太方便!
还开始学了Bash,之前面百度的时候让手写一个脚本
没写出来。。因为记得不清不楚
这几天就系统地学一下经典的abs教程
嗯,以后可以用Bash做更多事情了

终于挤牙膏样挤完了《万历十五年》第二遍
这本书对我影响还挺大的
作为一个明粉,一定要多看几遍
十一开始看《枪炮,病菌与钢铁》这本书
在书架摆了几个月了
这本书副标题起的那叫一个大《人类社会的命运》
另外一本起的这么大的只有《失控》了吧
不过确实讲的是大问题,人类社会演进的方向问题
听上去就很厉害,看了几章,确实有点意思

最近心情不太好,开始抽烟
抽的是博哥推荐的一种很淡的细烟
很淡很淡,抽完一根万宝路,再抽这个,完全没有冲劲,很好
基本一天一根的样子
这几天有点感冒,一天两根的样子

放假放得面试的东西都忘记了
睡觉睡得天昏地暗
假期结束又得面试了
找工作好难
哦,前几天还去了Offer寺
当然不是我迷信,这只是《仪式过程》所讲的仪式的一部分,嗯

之前写了一片重新装了一个Fedora 24的博客,那次装的时候为了系统速度比较快,把fedora装在了SSD上面,但我用的还是几年前买的三星的120GB的SSD,容量是捉襟见肘啊,只能从原来的windows系统分了35GB的空间给fedora,使用fedora自动分配后,挂载的可用空间只有29GB了,随着系统用的越来越久,剩余空间也就越来越少了,到现在只有10多G的可用空间了。幸好装Fedora的时候使用的LVM,这样可以很方便的进行扩容了。

Shrink Windows Disk

首先从windows的分区压缩一些空间出来,当然LVM是支持从不同磁盘扩容的,但是为了速度还是从SSD中压缩空间吧,这样window留70G左右,剩余40G给Fedora,能压出来15G左右(因为影音类文件都放在另一个硬盘,所以45GB左右的Linux空间可以用比较长时间了)。
但是windows压缩空间有一个限制,那就是使用系统的压缩空间时,如果有一些不可移动文件占据了空间,那就只能从没有这类文件的位置开始压缩空间。。也就是说虽然C盘有30G的剩余空间,却不能压缩出30G,像我的情况就只能压缩出6G。。。这时候可以自己捣鼓也可以使用一个软件 AOMEI Partition Assistant 进行扩容,使用非常方便。但是!有一个问题,那就是需要重启进入一个XXX PreOS的界面自动重新分区,双系统重新分区后。。会导致Grub引导失效,只能进入 Grub Rescue 界面。

修复引导

还好Grub的修复还是有很多路子的,也许可以从Grub Recue中捣鼓,但是更方便的做一个Fedora Linux进入系统重新安装grub。

阅读全文 »

大概两年前用过很长一段时间的Fedora+win7的双系统,最早用的fedora版本还是14、15的样子,长期使用过18-20,后面几代都只在虚拟机里试玩了一下,因为配置起来一套顺手的桌面其实很麻烦,f24之后一直想再装一下fedora,在virtual box里面玩了一会觉得太卡就决定装双系统,花了两天时间基本弄得顺手了。

在今年,我的windows下的工具大多更换了,从印象笔记到为知笔记,同步使用了坚果云,音乐一直是网易云音乐,幸好这些工具都有Linux版本的,装起来倒也不太费事,使用也还顺手。配置这个系统主要是一下几个方面:

  • gnome shell theme. 就是gnome的主题,包括gtk主题,shell主题,图标等等,我现在使用 zukitre的gtk+主题, shadow的Icons, OSX-EICap的cursor, Zuki-shell的shell theme。这些都是在gnome-tweak-tool里面配置
  • gnome-extension. 就是gnome-shell的扩展,这个非常重要,gnome的扩展性非常强,一些常用的扩展可以极大的方便操作,最常用的包括:applications menu, background logo, caffeine, coverflow alt-tab, dynamic top bar, launch new instance, media player indicator, openweather, place status indicator, simple dock, suspend button, topiconcs, user themes等
  • 输入法,切换到fcitx和rime,除了sublime外基本都可以正常使用
  • 工具类:网易云音乐,坚果云同步,为知笔记,WPS,mysqlworkbench, chrome,shadowsocks,vlc player,Atom, 甚至texstudio都有很好的支持
  • 鼠标手势,在windows下习惯了 Wgesture的全局手势,一开在Fedora下很不习惯,后来找到一个开源的 easystroke gesture recognition的软件,使用和Wgesture基本差不多,非常非常方便
  • 使用Roxterm替换gnome的terminal,roxterm是我最喜欢的一个终端工具,定制之后非常方便

最后的效果:

下面是安装时记录的一些问题,确实从头开始配置各种工具容易遇到非常多的问题,这里也是遇到一个记录一下,记得比较乱也不整理了,到时候再遇到能找到就可以了:

阅读全文 »

最近公司部署在阿里云上的服务器被恶意攻击了,大概几百台肉鸡不停地向某个接口发送请求。由于一些各种原因,过多的请求导致服务器CPU占用率几乎是一直在100%。虽然应用勉强还能使用,但是这样被请求服务器真是压力非常大。

由于公司现在还没有专职的运维去处理这些请求所以只好自己动手先做一些限制,大概两个思路:

  1. 对接口的请求限速
  2. 2.封禁一批IP

基础环境

先记录一下服务器的基本环境,双核,4G内存,Ubuntu 14.04,现在的web server是lighttpd,数据库是mysql。

接口限速

由于现在部署的代码使用旧的框架,本身没有对接口限速的功能,只能从web server方面入手。

现在的web server是lighttpd,lighttpd的特点是轻快,内存占用小,但是模块化不是很好,似乎在lighttpd上面做 rate limiting 不是那么方便,我觉得可以使用使用一个围魏救赵的方案:

搭建一个nginx作为前端server,在nginx这里做rate limit,nginx把请求发送到lighttpd,lighttpd不对外暴露端口,只接受来自nginx的请求。

在lighttpd的配置文件(/etc/lighttpd/lighttpd.conf)中加上

server.port = 80001

重启lighttpd,记得在防火墙中Drop所有8001端口的请求。

安装好nginx(推荐编译安装openresty)后,配置转发如下:

upstream lighttpd {
server 127.0.0.1:8001
}

server
{
...
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://lighttpd;
}
}

启动nginx后,原来所有的请求都会发送到nginx了,而对用户来说,感觉不到任何的变化。

有了nginx之后我们可以使用 ngx_http_limit_req_module 这个模块做限速了,具体内容可以参考nginx的文档。

定义限制请求域

rate limit首先要定义一个或多个zone,然后在特定的context使用它们。这些定义一般定义在http上下文中。

http {
## 对每一个IP的请求限制为1次每秒
limit_req_zone $binary_remote_addr zone=perip:10m rate=1r/s;

## 对一个server_name下的请求限制为10次每秒(这个数值有点低,一般会改大很多)
limit_req_zone $server_name zone=perserver:10m rate=10r/s;
}

使用请求限制

可以在 http, server,location 上下文使用上面定义的域,使用方法如下:

server {
...
limit_req zone=perip burst=5 nodelay;
limit_req zone=perserver burst=10;

location /api {
limit_req zone=perip burst=3 nodelay;
}
}

限速的配置是可继承的,当前级别没有配置就会从父级配置中继承:

These directives are inherited from the previous level if and only if there are no limit_req directives on the current level

关于 nodelay的配置,说明如下:

If delaying of excessive requests while requests are being limited is not desired, the parameter nodelay should be used

IP 限制

第二个思路是找出频繁请求的那些IP,在防火墙或者 web server 级别做限制,拒绝它们的请求。

首先通过请求日志(access_log)找出请求次数最多的前50个IP:

awk '{print $1}' /path/to/web-server-log/access.log | sort|uniq -c | sort -nr | head -n 50

我只是在nginx或者lighttpd层做限制,iptables在我手上很容易玩坏,不是很熟悉,就在web server做配置了:

nginx限制IP访问

nginx的配置很简单,在指定上下文deny掉指定的IP就可以了,如下:

location / {
deny 192.168.1.2;
allow 192.168.1.1/24;
allow 127.0.0.1;
deny all;
}

lighttpd限制IP访问

lighttpd的限制也非常方便,只不过要先对上面获得的50个ip做一些简单的处理,然后在ilghttpd.conf中加入下面的配置:

$HTTP["remoteip"] != "1.231.2.1|23.24.54.213|ip-3|ip-4|more-ip" {
url.access-deny = ( "" )
}

总结

第一种方法应该是更好的,或者说是必须的,但是我调了一下,限速的参数可能调太小了,导致正常的访问都不太好用了,之后需要继续调优参数。

第二种限制IP的方法也可以有,可以用一个计划任务隔一段时间就跑一批IP扔到禁止列表中,不过要是能加到iptables中,对服务器的压力就更小了,这个后面可以尝试一下。

命名空间

按照PSR的标准,应该是一个文件对应一个类,并且命名空间与文件系统路径一一对应,这样便于理解。但是也允许一个文件有多各类,甚至一个文件有多分命名空间,一个命名空间也可以分散在不同的文件/文件夹中,这都是允许的,但是不是推荐的做法。

因为命名空间和文件系统的对应关系是通过自动加载(auto_load)定义的,只要定义的spl加载器能找到要引用的类的实际文件就可以正常运行,但是最好不要使用违反PSR标准的命名空间。这不利于源代码的管理和调试。

面向接口编程

接口是两个对象的共同遵循的规约,它使得对象不在依赖于另一个对象是什么,而只依赖于它能做什么。面向接口使得我们能使用那些实现了某种接口的第三方代码。这样我们不需要知道第三方代码是怎么实现的,只要知道它们能做那些事就可以了。

Traits

Traits是PHP 5.4 引入的新特性。最初看到这个概念的时候觉得有点困惑,因为其他的语言基本没有traits的概念(Ruby有相似的概念)。Traits用来实现更细化的代码复用,它的行为更像类,但是看起来很像接口,但它并不是类或者接口。

Traits可以看作是类的部分实现(partial class implementaion),它能被用于多个PHP类中。在类的内部使用 use 关键字引入traits即可以把traits实现的功能加入该类中。

traits用来解决经典单继承模型难以解决的问题:两个不存在关联的类共享相似的行为。通过复杂的类型设计或者模式可以实现,但是这样的类型系统通常要非常复杂不利于理解,因为要为两个不相关的类设计一个本不存在的祖先类,而traits可以非常方便的在两个不相关的类中共享实现:通过把trait引入类中就可以了。

traits的使用和类很相似,通过trait关键字定义:

trait GeoTraits {
protected $lnt;

public function getLnt() {
...
}
// trait implementation
}

直接在类中使用traits:

class GeoClass {
use GeoTraits;
// other parts of this class
}

traits、类和接口都通过use关键字引入,不过traits是在类的内部引入,作为类实现的一部分使用的。

tratis的使用更像是一个预处理过程,PHP解释器会在编译期直接复制traits的内容到类中,解释器并不能保证这一行为不会导致代码的不兼容。所以要注意,如果在traits中使用了不是在trait中定义的属性或方法(即是定义在使用trait的类中的属性或方法)时,要保证这些属性或者方法是存在的。

Generators

Generator是PHP5.5引入的特性,到现在还很少被使用。Generator可以看作一个简单的遍历器(iterator)。generator不需要实现Iterator接口,而是在需要时计算、产生(yield)遍历的值。PHP的遍历器是实现计算好的数据集,而generator是在使用时返回值的,对于大量的数据集这样可以节省很多开销。

注意generator是一个只能遍历一遍的单向遍历器,不能回退,不能直接定位到某个元素。generator就是一个使用了yield关键字的普通函数。这个函数可以使用一次或者多次yield

function simpleGenerator() {
yield "val1";
yield "val2";
yield "val3";
}

foreach simpleGenerator() as $val {
echo $val;
}

调用一个generator函数会返回一个Generator类的对象,这个对象能使用foreach遍历,在每一次遍历中,generator会计算下一个值,因为是在请求值时才计算下一个返回的值,所以在处理很大的数据集时,generator并不需要使用很多的内存。比如:

function rangeGenerator($len) {
for ($i=0; i<$len; $i++) {
yield $i;
}
}

foreach (rangeGenerator(1000000) as $i) {
echo $i, PHP_EOF;
}

这里就并不需要分配一个 1000000 大小的数组,generator也可以用来读取大文件,而不是把整个文件读入内存中,下面是读取一个csv文件的示例:

function getRows( $file) {
$handle = fopen( $file, ' rb' ) ;
if ( $handle === false) {
throw new Exception( ) ;
}
while ( feof( $handle) === false) {
yield fgetcsv( $handle) ;
}
fclose( $handle) ;
}

foreach ( getRows( ' data. csv' ) as $row) {
print_r( $row) ;
}

其中fgetcsv是php提供的函数。

在有些时候generator能简化一些任务,当然不实用generator也可以实现所有的功能。

Closure/闭包

闭包和匿名函数都是PHP 5.3中引入的。然而很多开发者现在仍很少使用php的闭包和匿名函数。可能这些特性看起来就比较复杂吧。

php的闭包和js的闭包很相似,可以用相同的思路去理解。匿名函数其实是比较常见的,匿名函数可以被赋给一个变量,或者像一个对象一个传递。匿名函数常用来作为方法的回调。

闭包和匿名函数本理论上是两个不同的东西,但是PHP中把它们混为一谈了。PHP的闭包和匿名函数使用相同的语法,它们实际上是伪装为函数的对象,它们都是 Closure 类的实例, 闭包是一等值类型,就和 String和Integer一样。

PHP变量后面使用 () 时,如 $var() 这样的调用会尝试调用 __invoke() 魔术方法。

前面说过,匿名函数常作为方法的回调参数,如 array_mappreg_replace_callback()

PHP中的闭包使用和JS有很大不同,虽然都是闭包的理论。PHP的闭包需要使用 bindTo() 方法或者 use 关键字使用。PHP的闭包有一个状态附着(attach state)的概念,也就是必须手动将状态/变量(state)附着到一个闭包对象上(使用闭包的bindTo()方法)。一种更常用的方法是使用use关键字。

function enclosePerson($name) {
return function ($doComande) use ($name) {
return sprintf('%s %s', $name, $doCommand);
};
}

$clay = enclosePerson('Clay');
echo $clay('get me sweet tea');

从上面可以看出,需要手动将变量绑定到闭包中才可以在闭包内使用外部的变量。这和JS很不一样。上面的函数返回的是一个 Closure 对象实例,所以 $clay 有自己的属性和方法,常用的如 __invoke()bindTo() 方法。 bindTo方法有一些特殊的用法,如可以讲一个闭包对象绑定到另外的对象上。这样闭包可以访问该对象的成员对象(包括protected和private)的。

在PHP框架中的路由映射中常用bindTo方法,将匿名的路由回调函数绑定到应用对象(application object)上。

OPcache

从PHP 5.5开始集成了字节码缓存,那就是Zend OPcache。字节码缓存会存储预先编译的PHP字节码,这意味着解释器不需要在每次请求的时候都去读取、解析和编译PHP代码,而是直接读取预编译的字节码直接执行,这可以节省很多时间开销,提升性能。

旧的PHP默认没有开启OPcache,使用 --enable-opcache编译选项开启,然后在php.ini配置中,添加扩展: zend_extension=/path/to/opcache.so。注意如果需要使用xdebug的话,需要将opcache在xdebug之前加载。

OPcache的常用配置项包括

# 在开发环境这个选项设置为1,生产环境可以设置为0
opcache.validate_timestamps=1
opcache.revalidate_freq=0

内置Web Server

php -S localhost:4000

在项目目录使用上面的命令,可以启动内置的服务器

  1. 关于路由,见一个请求转发到控制器:
Route::get('/', function () {
return view('welcome');
});

// Controller_Class_Namw@function
Route::get('user/info', 'UserController@info');

// or as:
// Route::get('user/info', [
// 'as'=>'userinfo', 'uses' => 'UserController@info'
// ]);

Route::get('phpinfo', function() {
return phpinfo();
});
  1. Controller需要使用命令生成,不能自己新建文件生成:
php artisan make:controller nameController --plain
  1. 获得某个Route的url: $url = route('userinfo'),参数为路由别名。或者使用action方法,获得控制器下action的连接,$url = action('UserContrller@info'); Route::currentRouteAction() 可以获得当前的控制器和行为(action)
  2. 在 Route 中可以指定中间件,使用 middleware 键指定控制器的中间件,也可以在控制器的构造器中指定中间件: $this->middleware('auth');;
  3. Laravel提供隐式控制器,通过单个路由处理控制器的各种行为,有点类似于Yii的默认路由。 Route::controller('user', UserController); 不过要在控制器中加入方法,方法的名称应由它们所响应的 HTTP 动词作为开头,紧跟着首字母大写的 URI 所组成, 如 getIndex 会处理 get 请求的 index(默认) 动作。

这两年买了不少书,现在有的和正在看的一些书在这里列个清单。

外语

  1. 《大家的日语》 第一册 外研社
  2. 《标准日本语》 初级
  3. 《日语学习入门》
  4. 《赖世雄经典英语语法》

IT

  1. 《Python基础教程 第2版》 邮电出版社
  2. 《深入浅出NodeJS》 邮电出版社
  3. 《数据结构与算法分析–C语言描述》 机械工业出版社
  4. 《数据库系统基础教程》 机械工业出版社
  5. 《白帽子讲Web安全》 电子工业出版社
  6. 《MySQL入门很简单》 清华大学出版社
  7. 《计算机网络 第5版》 谢希仁 电子工业出版社
  8. 《Vim使用技巧》 邮电出版社
  9. 《精通正则表达式》 电子工业出版社
  10. 《人月神话》 清华大学出版社
    阅读全文 »