牛娇客(一一二)zz

发信人: newjoker (娇心依旧), 信区: Joke
标 题: 牛娇客(一一二)zz
发信站: 水木社区 (Sun Aug 21 23:57:15 2016), 站内

1.本届奥运女排赛中B组前四名淘汰了A组前四名,之后B组三四名灭了一二名,最后第四名打败第三名,完美收工。

2.美国女排刚刚走下领奖台,就在第一时间向奥组委提出异议:本届奥运会她们球队七胜一负取得第三名,而中国女排五胜三负却取得了冠军,这不合理,要求给美国女排单独重赛的机会。奥组委已经考虑美国队的建议,但是重赛的对手难以选择。现在美国女排正在赛场等待……

3.张怡宁对孩子说:“金牌你随便玩,你娘我多的是,但那个银牌你别动,我就那一块。”

4.不会日文的英国记者要采访不会英文的福原爱,找了个不会日文但会中文的美国翻译,英国记者用英文向美国翻译提问,美国翻译翻译成中文告诉福原爱,福原爱用东北话告诉美国翻译,美国翻译译成英文。这画风太清奇了…

5.要问这届奥运会我记最深刻的是什么。——“新加坡旁碧桂园森林城市”

6.女孩像心仪已久的男孩表白!男孩说:我有女朋友了。说完拿手机给女孩看手机。女孩望着漆黑的手机屏幕里倒映着自己的脸,留下了幸福的泪水!男孩把手机拿来一看,说:不好意思!忘记开机了!

7.新学期学生报到,一男同学自我介绍,大家好,我姓黄,名叫黄尚。这时旁边,一女同学站起来,脸色微微一红,介绍道,我姓李,名叫李婉姬。

8.物理课上,同学们都在做作业,老师说:“大家有什么问题,就尽管问我!”小明:“老师,牛顿的头发是在哪烫的?”

9.数学课上,老师正在解析几何,小明闲着无聊突然来了句:“我出个上联,老师你来对对看:上海自来水来自海上。”老师愣了下后说:“明天到操场……”小明心领神会:“老师你真牛!”老师:“罚跑十圈!”

10.小明:报告老师,我想拉屎。
老师:老师教过你用词要文雅有内涵,不要粗俗嘛。
小明:报告老师,“菊部”地区即将发生大面积泥石流灾害,火速请求马上进行人员撤离!

11.“其实根本没有初吻这回事儿,随着上皮细胞的不断更新,每天都是初吻。”
“第一次听人把滥情说得这么有技术含量。”

12.去超市买套套,因为比较害羞,顺便拿了一盒蚊香做掩护。
排队结账的时候还是被别人看到了,当我结完账走了几步就听到后面有人议论:“那个人肯定是打野战去,买套套还买蚊香。”

13.今天去吃面,隔壁桌一中年女,嘴里还含着饺子走过来对我说:“处女要吗?”
我简直惊了个呆:“你还处女呢阿姨?”

小段抢鲜看0821

发信人: Tue (昵称), 信区: Joke
标 题: 小段抢鲜看0821
发信站: 水木社区 (Sun Aug 21 13:33:50 2016), 站内

1.中国女排低开高走,盘中大幅震荡,午盘发力,最后封死涨停板!郎平该考虑去当中国证监会主席或中国足协主席了!

2.中国体育代表团的里约奥运之行可以概括为四句话:女排把观众打哭,乒乓把对手打哭,男篮被打哭,男足在家哭。

3.看完了林丹和李宗伟的比赛,互换球衣的一刻,真心让我感动。所以我不管多困都坚持看完了女子羽毛球单打决赛。 结果她们俩打完后竟然没换球衣!太让我失望了!没素质!

4.记者:“大爷,您今年贵庚啊?”
大爷:“九十有六了。”
记者:“这么大岁数怎么还在外面卖桃子了?”
大爷:“哎,别提了,我也不想啊”
记者:“怎么回事呢?”
大爷:“卖不完回家我妈不让我吃饭!”

5.晚上关灯后,想勾引老公,从后面抱着老公用娇滴滴的声音说,我是你的梦中情人林志玲……老公说,为什么我感觉不到林志玲的胸?

6.媳妇:“结婚到现在,你有几次有想换个老婆的想法?”
我:“你有几次想换老公,我就有几次想换老婆呗。”
媳妇一个耳光呼过来,大怒:“居然这么多次想换了我!找死!”

7.公司新来的女汉子去相亲,张口闭口卧槽……特么……吓跑了不少相亲男。
我说你就不能温柔文静点吗?
女汉子瞅我一眼,嚷嚷道:卧槽,我要特么能文静点,就凭老娘的长相用得着相亲吗?

8.今天闺蜜和我诉苦,说她男友每次和自己啪啪啪都不接吻,也没前戏,让她转过身就一个姿势。闺蜜就问她男友,男友说了句没把她气死。闺蜜男友说,你不转过去我硬不起来。

9.朋友第一次和老板去吃饭,吃完后习惯性喊了一句:“老板,买单!”老板起身去结账了……现在朋友已经准备辞职了。

10.洗澡的时候宝宝闯进来尿尿,出去后跟老公大声说:爸爸,我看到妈妈还在洗澡,咪咪好大!
老公回了他一句:等你长大了,就不会觉得大了!

11.老公开车接我回家,路上有只鸡蹲在那儿,按喇叭也不走。老公就让我下去赶走那只鸡,我不想下去,说:赶什么赶,人家等生意呢!

12.当年,易中天给一群企业家讲课,期间问某学员一个问题:听了几次课后,请问你现在企业的发展态势如何?
某学员:如日中天!
易中天:你特么得一次性交双倍费用!

13.早上要上班,两岁的女儿拉着我不让我走。我和她解释,爸爸不工作你吃什么喝什么啊?女儿忽闪着懵懂的眼睛看着我,奶声奶气地说:吃饭……喝奶……

Nicholas C. Zakas:我收到的最好的职业建议

Nicholas C. Zakas 是全世界最著名的 JavaScript 程序员之一。 Nicholas 编写的技术书有:《JavaScript高级程序设计》、《 高性能JavaScript》等。这篇文章翻译自他的博文,看了这篇文章,对于自己还是感触蛮深的,想想自己的职业发展,确实是还有很多泥潭没有跳出来。以下是翻译内容:

最近我与一同事有一次有意思的讨论。我们回忆了各自所走过的职业历程以及不同个性如何长期消极影响我们的职业。事实情况是,我曾经是那种从大学里走出来的令人讨厌的人(有些人可能会说我现在仍然是那种人,但这是另一回事儿)。当时我很傲慢并且很刻薄,是一个十足的愤青。我自以为我很了解自己的性格并且为这种性格感到骄傲。

我曾经经常指出更有经验的工程师的错误之处。尽管我所提出的大部分错误是正确的,但是由于我的个性问题使得解决这些错误并没有这么高效。比如在一次对话中,其中的一名高级工程师突然恶狠狠的说道,“假如你不闭嘴,我就用屎把你赶出去。”我只是笑笑因为知道他不敢。一年之后我就意识到,他是真心想做这件事的。

从那时开始我成长了很多,开始学习如何说话,如何尊重人。这种挖苦在职业环境下得到了控制;当我与好朋友在一起的时候,我把它们放到一边。这些自我控制能力伴随着其它无价的教训并非来自自身内部,而是由一路上的人生导师引导的。如果没有他们,我的人际关系将会使我的职业生涯变的很糟糕。

因为工作中接触到很多优秀的人,所以我是幸福的。我的经理们一直以来将自己塑造成性格很好的人。我为他们感到自豪。更甚,受到他们影响,我不仅成为一名好的编程人员—-也成为一名优秀团队成员和优秀个人。他们对我的人生影响很大,以致于我经常将他们的建议讲给我所指导的同事们。

我发现这些建议具有普遍适用性,所以决定将它们分享给大家。当然,有些内容是经过改述的(本人记性不大好,不能把每个词都记住),但相信我现在已经抓住了主要思想。

不要成为只会做快餐的厨师

我的第一份工作持续了8个月,之后这家公司就关闭了。当跟经理讨论下一步我该做什么的时候,他建议我:

Nicholas,你的价值不只有你的代码。无论接下来的路是什么,确保你自己不是一个仅会做快餐的厨师。不要去接受那些有明确目标并且步骤已经很详细的工作。你应该去那些赏识你的洞察力以及构建产品能力的公司。

我牢记这句话很多年。做代码实现者不够好—-我们应该参与到整个开发过程中。一名好的工程师不仅是按部就班的实现功能,还应该给予反馈,与产品的拥有者一起工作,这样才能构造出更好的产品。很幸运,我的工作选择都很明智并且我从来不会在一家不尊重、不重视我的洞察力的公司待很长时间。

自我推销

有一天,在Yahoo的经理将我拉到一边给了我些建议。他监督我的工作,后来发现我有点内向:

你工作很棒。我喜欢你代码的风格以及它的连贯性。然而,其他人并没有看到。为了使你现在的工作得到好评,你应该让别人看到你的代码。你需要做一些自我推销来引起注意。

刚开始我并没有理解他的话,但后来我明白了其中道理。即使你工作很棒,但如果没有人看到你所做的内容,这并没有帮到你多少。你经理能支持你,但不能为你做证明。你组织里的人需要知道你的价值所在,最好的方式就是告诉他们你做了什么。

我将这个建议告诉过许多同事了。自我推销并不是说,“看我,我很牛逼。”它意味着让别人知道你的工作有了巨大进展或者让他们知道你学到了一些新内容。它意味向别人展示你所骄傲的成果。它意味着庆祝自己以及别人的成就。它意味着向你所在的组织证明你的价值。坐在角落默默敲代码的工程师总是有一些神秘感—-不要那样。一封简短的邮件,“好,我完成了新邮件的布局。你看看有什么建议吗。”,往往会起到很大的作用。

“人”比技术重要

在职业生涯的早期阶段,我是头衔驱动型。我总是想着如何做才能被提拔。在雅虎主页上与新经理的第一次一对一会议中,我问需要做什么才能得到提拔。他的话仍然在脑海中盘旋:

从某种意义上讲,你应该结束对自己技术的评判,开始关注与人交流的方式。

之后,我没有收到过对软件工程这个职业比这更具洞察力的见解了。他完全正确。在那时,没有人怀疑我的技术能力。我以写高质量,几乎零bugs的代码而出名。我所缺少的是领导能力。

从那时起,我看到无数工程师处于他们职业生涯的瓶颈期。他们聪明,写着一手好代码,然而缺乏有效的与同事高效交流的能力。这将他们困在原地。一旦有人困在他们软件工程生涯的瓶颈期,我都会给他们这个建议。

“问题”不是问题

我在Yahoo失意过一段时间。可能“失意”这个词并不正确,更像是愤怒。我经常愤怒地与人争论。结果事情变的很糟糕,我自己也不想这样。有一天,我心情非常差,就问我导师如何在面对这么多问题时保持冷静的。他回答:

很容易。这些问题都不是问题。有这么多垃圾代码混到站点中,致使其崩溃,那又如何?工作并不是你生活的全部。这些不是真正的问题,他们是工作上的问题。工作之外所发生的事情才是值得关注的。我回到家里,我妻子在等我。那才是幸福的。

那时,我从马萨诸塞州搬到加州,人生地不熟,很难交到朋友。这样工作就是我的全部,它是我保持正常的寄托所在,所以一旦工作出现问题也就意味着我的生活也出现问题。通过这次谈话我明白生活中需要某项我能够回去然后忘掉工作中遇到的麻烦的事物。

他是对的,当我调整心态并且将这些工作中遇到的令人恼火的事情重新归为“工作”的时候,我能够思考的更加清楚。我还能够让自己冷静下来与人进行更愉悦的交流。

权威,由你做主

当被提升为雅虎的首席工程师时,我与主管一起讨论这个职位所需要承担的责任。我明白这个职位更应该是个领导者,但是我并不知道如何使自己更具权威性。我请他帮忙。这是他所说的:

我不能告诉你应该如何具有权威性,每个人的风格不同,你应该自己发掘出来。你应该做的是找到适合自己的风格。我不能告诉你你的风格是什么,但是你应该找到适合这个职位的。

那一年,我花了很多时间来观察那些有权威的人以及他们与人交流的方式。我把他们走路的方式,讲话的方式以及处理问题的方式记录了下来。我试过许多不同的方式,最后终于找到了能为我用的风格。我的风格只适合我,任何处于权威性位置的人都会经历同样痛苦的学习过程。我的优势是领导一开始就跟我讲明了情况。

从“怎样?”转到“什么?”

在与经理的一次交谈中,我问道这个新职位的期望是什么。他回答说:

到现在为止,你的职业在回答“怎样?”这个问题。即我们告诉你应该做什么然后你想出怎样做。而从这一刻开始,你应该回答的问题是“什么?”。我希望你能够过来告诉我应该做什么。

我看到许多工程师都在这个部分犯错误。如果没有这个建议我同样会陷入困境。从“怎样?”转到“什么?”是很困难的,并且需要许多时间来发展。你需要对自己所向往的以及所关注的事情有一个比较成熟的认识。毕竟,假如你能够花费时间在任何你想的事情上,你也应该独自对自己所创作的作品负责。

在盒子中,我们称其为“开环运行”,意味着在最少的监督下你完成工作并且仍然对组织和公司有一个整体的积极影响。就在这一阶段许多工程师失败了,我将这个建议给那些努力想要到下一阶段的工程师。

表现出你在负责

以往开会的时候,我只是坐在那儿并不知道该讲些什么。在与主管的一次面对面交谈中,我提到我只是在开会,并不知道我为什么会在那儿并且也没做什么贡献。他说道:

以后永远都不要这样。假如你在会议中,那是因为你参加了。假如不确定自己为什么会在那儿,停下来问一问。如果你不需要在那儿,那就离开。你在一个领导的位置,那就表现的像领导。不要静静的走进一个房间。只要表现出你在负责,那么人们就会相信。

从这个建议里,我的导师使我想起从高中学到的一个教训:没有人知道你什么时候在表演。假如你很紧张但是表现出并不紧张的样子,那么别人就不会知道你很紧张。领导能力也是一样的。一句古语“久演必成真”出现在脑海中。从那时,我从来没有在会议中静静的坐着。我确保自己只去参加那些需要我参加的会议。

让他们赢

我经历过一段时期,在这段时期团队中有许多争论。我为自己使用权威来结束这些争论而感到很满意。我有一个“我的规则是最终的结果”的心态,我的经理注意到这件事情并且给我建议说:

我看到你们团队有许多争论,而你经常逼进他们,赢了很多。我知道大部分时间你是对的,但每隔一会儿应该让他们赢。选择那些对你要紧的事情,对这些进行推进,其它的事情让他们赢。没有必要赢取每一次争论。

这是一则我一开始就坚持的建议。几乎所有时候我都是正确的,那为什么应该让其他人赢呢?然而,随着我的成长我开始相信他的本能,我决定试一试。结果是:争论减少了。他们不想要必须赢过我一次了,并且反过来,我能够更好的识别不需要太关心的事。我坚持那些重要的问题,将那些不重要的事情让别人来解决。所有对话的强烈程度都大大的降低了。

结论

回头看看那个刚刚毕业、非常无礼的小男孩,我的职业生涯可能非常不一样。我曾经被认为是一个不满现状,聪明但是很难伺候的人。假如不是因为一路上所遇到的导师以及在职业初期所遇到的一些令人羞辱的失败,我的交际能力(缺乏)会令我疲惫不堪。这些天,我经常找到那些比我更具经验的人并且向他们索取建议。我可能不会再犯一些大的错误,但是我也不会等着一个错误发生然后去找个我信任的人问经验性见解。

在Yahoo的接近五年时间是我职业生涯中变化最大的。我工作面对的都是大规模的有趣问题,但是我更庆幸自己能够同一系列非常优秀的经理和导师在一起工作。将我变成现在所自豪的人(无论是工作还是生活上的)的原因是那些对话。

假如我能够给你们一条最重要的建议的话,那就是:找到从某一方面(无论是技术上还是组织能力上等方面)比你明智的人,然后“黏”上他。比如如果你们能够定期的一起吃午饭或者喝咖啡,那么就开始挖掘他们脑袋里的大量知识。通过这样做,你的职业生涯甚至你的生活都会变的非常不同。

原文链接:https://www.nczonline.net/blog/2013/10/15/the-best-career-advice-ive-received/

No related posts.

使用sftp代替ftp

从第一次使用ftp到现在已经过了好多年,先前一直用着,也没有感觉到有什么不妥。无意间了解到sftp,感觉是时候将ftp淘汰了。

ftp虽然非常的方便,但是还是存在着一些问题:

  • ftp需要安装服务器端软件,如Linux下的vsftpd和Windows下的Serv-U,配置比较麻烦不说,还有可能存在软件漏洞,且Serv-U是收费的。
  • ftp采用的是明文的密码,在网络传输者存在一定的风险。

sftp的出现可以很好的解决上述问题,sftp是Secure File Transfer Protocol的缩写,安全文件传送协议。可以为传输文件提供一种安全的加密方法。sftp 与 ftp 有着几乎一样的语法和功能。SFTP 为 SSH的一部分,SFTP是使用加密传输认证信息和传输的数据,所以,使用SFTP是非常安全的。但是,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低一些。

另外sftp是不需要另外安装的,因为是SSH自带,所以会更省系统资源,对新手来说比较简单。Windows下常见的FTP客户端软件也都是支持sftp协议的。如:Filezilla、Flashfxp、cuteftp等。默认情况下使用sftp会登录到该用户的目录下。如果是自己的服务器,那么就不需要再做其他的配置了,如果需要给每个账号配置不同的目录权限,请自行搜索,网上的资料较多。

Redis在Linux及Window的安装

Redis在Linux的安装(CentOS)

方案一:自行编译安装

官网上给出的安装流程如下:

$ wget http://download.redis.io/releases/redis-3.2.3.tar.gz
$ tar xzf redis-3.2.3.tar.gz
$ cd redis-3.2.3
$ make

编译完成后二进制文件放在src文件夹下

执行

src/redis-server

  即可启动服务。

上述的流程非常的简单,而实际安装过程中并没有这么简单。

1、安装开发包组

yum groupinstall "Development Tools" -y

2、获取安装文件

wget http://download.redis.io/releases/redis-3.2.3.tar.gz

3、解压文件,并移动到需要安装的目录

tar -xzvf redis-3.2.3.tar.gz
mv redis-3.2.3 /usr/local/redis

4、进入目录编译安装

cd /usr/local/redis
make
make install
make test

5、设置配置文件路径

mkdir -p /etc/redis
cp redis.conf /etc/redis

6、修改配置文件,设置以后台程序方式运行

vi /etc/redis/redis.conf
仅修改: daemonize yes (no-->yes)

7、启动

/usr/local/bin/redis-server /etc/redis/redis.conf

8、查看启动

ps -ef | grep redis

10、使用客户端

如果redis-cli没有反应,重启下服务器就可以了(具体原因未知)

[root@localhost ~]# redis-cli
127.0.0.1:6379> ping
PONG

11、关闭客户端

redis-cli shutdown

12、开机启动配置

CentOS 6 开机启动:

开机启动要配置在 rc.local 中,而 /etc/profile 文件,要有用户登录了,才会被执行。

echo "/usr/local/bin/redis-server /etc/redis/redis.conf &" >> /etc/rc.local

CentOS 7 开机启动:

创建文件:/usr/lib/systemd/system/redis.service,文件内容为:

[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=/usr/bin/redis-server /etc/redis/redis.conf --daemonize no
ExecStop=/usr/bin/redis-shutdown

[Install]
WantedBy=multi-user.target

然后建立软链接:

ln -s  /etc/systemd/system/multi-user.target.wants/redis.service to /usr/lib/systemd/system/redis.service

13、开放防火墙端口:

CentOS 6.7:

iptables -I INPUT -p tcp -m tcp --dport 6379 -j ACCEPT
/etc/rc.d/init.d/iptables save
service iptables restart

CentOS 7:

centos7以后,内置的防火墙从iptables变成了firewalld。

firewall-cmd --permanent --zone=public --add-service=redis-server
firewall-cmd --reload

方案二:使用Yum安装(CentOS 7)

1、安装epel

yum -y install epel-release

2、执行执行redis的安装

yum -y install redis

3、修改相关的配置,配置文件所在位置:

/etc/redis.conf
/etc/redis-sentinel.conf

4、启动、停止、重启redis服务器和查看Redis服务器状态

systemctl start redis.service
systemctl stop redis.service
systemctl restart redis.service
systemctl status redis.service

5、打开或关闭开机启动

systemctl enable redis.service
systemctl disable redis.service

Redis在Windows上的安装

下载地址:https://github.com/MSOpenTech/redis/releases

在解压的目录下运行:

redis-server redis.windows.conf

 即可启动Redis。

可以通过双击目录下的redis-cli.exe 打开客户端工具。

其实Redis是可以安装成windows服务的,开机自启动,命令如下:

redis-server --service-install redis.windows-service.conf --loglevel verbose

安装完之后,就可看到Redis已经作为windows服务。但是安装好之后,Redis并没有启动,启动、关闭命令如下:

redis-server --service-start
redis-server --service-stop

另外还可以安装多个实例

redis-server --service-install –service-name redisService1 –port 10001
redis-server --service-start –service-name redisService1
redis-server --service-install –service-name redisService2 –port 10002
redis-server --service-start –service-name redisService2
redis-server --service-install –service-name redisService3 –port 10003
redis-server --service-start –service-name redisService3

卸载服务命令:

redis-server --service-uninstall

Windows下Redis GUI管理工具推荐:http://redisdesktop.com/

参考地址:

Python最佳实践之virtualenv

virtualenv是一个能把你的应用隔离在一个虚拟环境中的工具。 一个虚拟环境是一个包含了你的应用依赖的软件的文件夹。简单的描述virtualenv的作用:

  • virtualenv可以让你给不同的项目指定同样的依赖包的不同版本。
  • virtualenv可以让你方便的在多台服务器上部署相同的以来环境。

virtualenv的安装非常简单,只需

pip install virtualenv

 即可。

一、如何使用virtualenv构建独立的虚拟环境?

1、virtualenv的安装

pip install virtualenv

2、创建虚拟环境

首先到使用命令行移动到想要存在虚拟环境的文件夹,然后执行:

D:\>mkdir myenv

D:\>cd myenv

D:\myenv>virtualenv venv
New python executable in D:\myenv\venv\Scripts\python.exe
D:\myenv\venvInstalling setuptools, pip, wheel...Collecting setuptools
  Downloading http://mirrors.aliyun.com/pypi/packages/cd/48/45dee63e94368e331cfd8d90d1e804e8ad0c0d055e677ef2c1317de863e1/setuptools-25.4.0-py2.py3-none-any.whl (459kB)
Collecting pip
Collecting wheel
Installing collected packages: setuptools, pip, wheel
Successfully installed pip-8.1.2 setuptools-25.4.0 wheel-0.29.0
done.

其中myenv是存在所有虚拟环境的文件夹,在执行完命令后就myenv的文件夹下就生成了一个venv的文件夹,这个文件夹即为本次生成的虚拟环境。

3、激活虚拟环境

Linux环境下可以通过如下命令激活:

source venv/bin/activate

而Windows下的激活命令是:

venv\Scripts\activate

你也许注意到了,你的shell提示符发生了改变。 virtualenv在它前面添加了当前被激活的virtual environment,所以你能意识到你并不存在于全局系统环境中。

D:\myenv>venv\Scripts\activate

(venv) D:\myenv>

当一个virtual environment被激活后,在虚拟环境下使用pip安装的包都会安装到virtual environment中而不是全局系统环境。

如果你想离开virtual environment,在命令行中执行deactivate即可:

(venv) D:\myenv>deactivate
D:\myenv>

二、如何迁移virtualenv构建独立的虚拟环境?

比如说想把开发环境迁移到线上环境,方法非常的简单:

1、生成目前所在虚拟环境的所有依赖包信息

(venv) D:\myenv>pip freeze > requirements.txt
aniso8601==1.1.0
click==6.6
Flask==0.11.1
Flask-Admin==1.4.2
Flask-Login==0.3.2
Flask-OAuth==0.12
Flask-RESTful==0.3.5
Flask-SQLAlchemy==2.1
Flask-WTF==0.12
httplib2==0.9.2
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
oauth2==1.9.0.post1
python-dateutil==2.5.3
pytz==2016.6.1
requests==2.11.1
six==1.10.0
SQLAlchemy==1.0.14
Werkzeug==0.11.10
WTForms==2.1

同时会在刚在命令行所在的目录下生成一个requirements.txt文件,文件中的内容和上述返回的内容一致。

2、在新的服务器的虚拟环境中批量安装requirements.txt的包。

pip install -r requirements.txt

随着项目增长,你可能会发现pip freeze中列出的每一个包并不再是运行应用所必须的了。 也许有些包只是在开发时用得上。pip freeze没有判断力;它只是列出了当前安装的所有的包。所以你只能手动记录依赖的变动了。 你可以把运行应用所需的包和开发应用所需的包分别放入对应的require_run.txt和require_dev.txt。

注意:在freeze或install依赖包时,确保你正为于正确的virtual environment之中。

三、使用virtualenvwrapper更加方便的管理虚拟环境

Virtaulenvwrapper是virtualenv的扩展包,用于更方便管理虚拟环境,它可以做:

  • 将所有虚拟环境整合在一个目录下
  • 管理(新增,删除,复制)虚拟环境
  • 切换虚拟环境

在安装Virtaulenvwrapper之前,首先要确保已经安装了virtualenv。

Linux下安装命令:

pip install virtualenvwrapper

安装完成后并不能直接使用virtualenvwrapper,还需要进一步进行环境设置:

创建目录用来存放虚拟环境:

mkdir $HOME/Envs

编辑 ~/.bashrc,在文件最后追加如下内容:

export WORKON_HOME=$HOME/Envs
source /usr/local/bin/virtualenvwrapper.sh

运行:

$ source ~/.bashrc

 保存配置信息。此时virtualenvwrapper就可以使用了。virtualenvwrapper的基本使用方式:

  • 列出虚拟环境列表:
    workon 或者 lsvirtualenv
  • 新建虚拟环境: 
    mkvirtualenv [虚拟环境名称]
  • 启动/切换虚拟环境:
    workon [虚拟环境名称]
  • 删除虚拟环境:
    rmvirtualenv [虚拟环境名称]
  • 离开虚拟环境:
    deactivate

Windows下安装命令:

pip install virtualenvwrapper-win

参考链接:

关于高可用的系统

HighAvailability-BK在《这多年来我一直在钻研的技术》这篇文章中,我讲述了一下,我这么多年来一直在关注的技术领域,其中我多次提到了工业级的软件,我还以为有很多人会问我怎么定义工业级?以及一个高可用性的软件系统应该要怎么干出来?这样我也可以顺理成章的写下这篇文章,但是没有人问,那么,我只好厚颜无耻的自己写下这篇文章了。哈哈。

另外,我在一些讨论高可用系统的地方看到大家只讨论各个公司的技术方案,其实,高可用的系统并不简单的是技术方案,一个高可用的系统其实还包括很多别的东西,所以,我觉得大家对高可用的系统了解的还不全面,为了让大家的认识更全面,所以,我写下这篇文章

理解高可用系统

首先,我们需要理解什么是高可用,英文叫High Availability(Wikipedia词条),基本上来说,就是要让我们的计算环境(包括软硬件)做到full-time的可用性。在设计上一般来说,需要做好如下的设计:

  1. 对软硬件的冗余,以消除单点故障。任何系统都会有一个或多个冗余系统做standby
  2. 对故障的检测和恢复。检测故障以及用备份的结点接管故障点。这也就是failover
  3. 需要很可靠的交汇点(CrossOver)。这是一些不容易冗余的结点,比如域名解析,负载均衡器等。

听起似乎很简单吧,然而不是,细节之处全是魔鬼,冗余结点最大的难题就是对于有状态的结点的数据复制和数据一致性的保证(无状态结点的冗余相对比较简单)。冗余数据所带来的一致性问题是魔鬼中的魔鬼:

  • 如果系统的数据镜像到冗余结点是异步的,那么在failover的时候就会出现数据差异的情况。
  • 如果系统在数据镜像到冗余结点是同步的,那么就会导致冗余结点越多性能越慢。

所以,很多高可用系统都是在做各种取舍,这需要比对着业务的特点来的,比如银行账号的余额是一个状态型的数据,那么,冗余时就必需做到强一致性,再比如说,订单记录属于追加性的数据,那么在failover的时候,就可以到备机上进行追加,这样就比较简单了(阿里目前所谓的异地双活其实根本做不到状态型数据的双活)。

下面,总结一下高可用的设计原理:

  • 要做到数据不丢,就必需要持久化
  • 要做到服务高可用,就必需要有备用(复本),无论是应用结点还是数据结点
  • 要做到复制,就会有数据一致性的问题。
  • 我们不可能做到100%的高可用,也就是说,我们能做到几个9个的SLA。

高可用系统的技术解决方案

我在《分布式系统的事务处理》中引用过下面这个图:这个图来自来自:Google App Engine的co-founder Ryan Barrett在2009年的Google I/O上的演讲《Transaction Across DataCenter》(视频: http://www.youtube.com/watch?v=srOgpXECblk

Transaction Across DataCenter

这个图基本上来说是目前高可用系统中能看得到的所有的解决方案的基础了。M/S、MM实现起来不难,但是会有很多问题,2PC的问题就是性能不行,而Paxos的问题就是太复杂,实现难度太大。

总结一下各个高可用方案的的问题:

  • 对于最终一致性来说,在宕机的情况下,会出现数据没有完全同步完成,会出现数据差异性。
  • 对于强一致性来说,要么使用性能比较慢的XA系的两阶段提交的方案,要么使用性能比较好,但是实现比较复杂的Paxos协议。

注:这是软件方面的方案。当然,也可以使用造价比较高的硬件解决方案,不过本文不涉及硬件解决方案。

另外,现今开源软件中,很多缓存,消息中间件或数据库都有持久化和Replication的设计,从而也都有高可用解决方案,但是开源软件一般都没有比较高的SLA,所以,如果我们使用开源软件的话,需要注意这一点。

高可用技术方案的示例

下面,我们来看一下MySQL的高可用的方案的SLA(下图下面红色的标识表示了这个方案有几个9):

mysql-high-availability-solutions-feb-2015-webinar-9-638

图片来源:MySQL High Availability Solutions

简单解释一下MySQL的这几个方案(主要是想表达一个越多的9就越复杂)

  • MySQL Repleaction就是传统的异步数据同步或是半同步Semi-Sync(只要有一个slave收到更新就返回成功)这个方式本质上不到2个9。
  • MySQL Fabric简单来说就是数据分片下的M/S的读写分离模式。这个方案的的可用性可以达到99%
  • DRBD通过底层的磁盘同步技术来解决数据同步的问题,就是RAID 1——把两台以上的主机的硬盘镜像成一个。这个方案不到3个9
  • Solaris Clustering/Oracle VM ,这个机制监控了包括硬件、操作系统、网络和数据库。这个方案一般会伴随着节点间的“心跳机制”,而且还会动用到SAN(Storage Area Network)或是本地的分布式存储系统,还会动用虚拟化技术来做虚拟机的迁移以降低宕机时间的概率。这个解决方案完全就是一个“全栈式的解决方案”。这个方案接近4个9。
  • MySQL Cluster是官方的一个开源方案,其把MySQL的集群分成SQL Node 和Data Node,Data Node是一个自动化sharing和复制的集群NDB,为了更高的可用性,MySQL Cluster采用了“完全同步”的数据复制的机制来冗余数据结点。这个方案接近5个9。

那么,这些2个9,3个9,4个9,5个9是什么意思呢?又是怎么来的呢?请往下看。

高可用性的SLA的定义

上面那些都不是本文的重点,本文的重点现在开始,如何测量系统的高可用性。当然是SLA,全称Service Level Agrement,也就是有几个9的高可用性。

工业界有两种方法来测量SLA,

  • 一个是故障发生到恢复的时间
  • 另一个是两次故障间的时间

但大多数都采用第一种方法,也就是故障发生到恢复的时间,也就是服务不可用的时间,如下表所示:

系统可用性% 宕机时间/年 宕机时间/月 宕机时间/周 宕机时间/天
90% (1个9) 36.5 天 72 小时 16.8 小时 2.4 小时
99% (2个9) 3.65 天 7.20 小时 1.68 小时 14.4 分
99.9% (3个9) 8.76 小时 43.8 分 10.1 分钟 1.44 分
99.99% (4个9) 52.56 分 4.38 分 1.01 分钟 8.66 秒
99.999% (5个9) 5.26 分 25.9 秒 6.05 秒 0.87 秒

比如,99.999%的可用性,一年只能有5分半钟的服务不可用。感觉很难做到吧。

就算是3个9的可用性,一个月的宕机时间也只有40多分钟,看看那些设计和编码不认真的团队,把所有的期望寄托在人肉处理故障的运维团队, 一个故障就能处理1个多小时甚至2-3个小时,连个自动化的工具都没有,还好意思在官网上声明自己的SLA是3个9或是5个9,这不是欺骗大众吗?

影响高可用的因素

老实说,我们很难计算我们设计的系统有多少的可用性,因为影响一个系统的因素实在是太多了,除了软件设计,还有硬件,还有每三方的服务(如电信联通的宽带SLA),当然包括“建筑施工队的挖掘机”。所以,正如SLA的定义,这不仅仅只是一个技术指标,而是一种服务提供商和用户之间的contract或契约这种工业级的玩法,就像飞机一样,并不是把飞机造出来就好了,还有大量的无比专业的配套设施、工具、流程、管理和运营

简而言之,SLA的几个9就是能持续提供可用服务的级别,不过,工业界中,会把服务不可用的因素分成两种:一种是有计划的,一种是无计划的。

无计划的宕机原因

下图来自Oracle的 《High Availability Concepts and Best Practices

 

unplaned_downtime有计划的宕机原因

下图来自Oracle的 《High Availability Concepts and Best Practices

planned_downtime

 

我们可以看到,上面的宕机原因包括如下:

无计划的

  • 系统级的故障 –  包括主机、操作系统、中间件、数据库、网络、电源以及外围设备
  • 数据和中介的故障 – 包括人员误操作、硬盘故障、数据乱了
  • 还有:自然灾害、人为破坏、以及供电问题。

有计划的

  • 日常任务:备份,容量规划,用户和安全管理,后台批处理应用
  • 运维相关:数据库维护、应用维护、中间件维护、操作系统维护、网络维护
  • 升级相关:数据库、应用、中间件、操作系统、网络、包括硬件升级

真正决定高可用系统的本质原因

从上面这些会影响高可用的SLA的因素,你看到了什么?如果你还是只看到了技术方面或是软件设计的东西,那么你只看到了冰山一角。我们再仔细想一想,那个5个9的SLA在一年内只能是5分钟的不可用时间,5分钟啊,如果按一年只出1次故障,你也得在五分钟内恢复故障,让我们想想,这意味着什么?

如果你没有一套科学的牛逼的软件工程的管理,没有牛逼先进的自动化的运维工具,没有技术能力很牛逼的工程师团队,怎么可能出现高可用的系统啊

是的,要干出高可用的系统,这TMD就是一套严谨科学的工程管理,其中包括但不限于了:

  • 软件的设计、编码、测试、上线和软件配置管理的水平
  • 工程师的人员技能水平
  • 运维的管理和技术水平
  • 数据中心的运营管理水平
  • 依赖于第三方服务的管理水平

深层交的东西则是——对工程这门科学的尊重:

  • 对待技术的态度
  • 一个公司的工程文化
  • 领导者对工程的尊重

所以,以后有人在你面前提高可用,你要看的不是他的技术设计,而还要看看他们的工程能力,看看他们公司是否真正的尊重工程这门科学

其它

有好些非技术甚至技术人员和我说过,做个APP做个网站,不就是找几个码农过来写写代码嘛。等系统不可用的时候,他们才会明白,要找技术能力比较强的人,但是,就算你和他们讲一万遍道理,他们也很难会明白写代码怎么就是一种工程了,而工程怎么就成了一门科学了。其实,很多做技术的人都不明白这个道理

包括很多技术人员也永远不会理解,为什么要做好多像Code Review、自动化运维、自动化测试、持续集成之类这样很无聊的东西。就像我在《从Code Review 谈如何做技术》中提到的,阿里很多的工程师,架构师/专家,甚至资深架构师都没有这个意识,当然,这不怪他们,因为经历决定思维方式,他们的经历的是民用级的系统,做的都是堆功能的工作,的确不需要。

看完这些,最后让我们都扪心自问一下,你还敢说你的系统是高可用的了么? ;-)

(全文完)


关注CoolShell微信公众账号可以在手机端搜索文章

(转载本站文章请注明作者和出处 酷 壳 – CoolShell.cn ,请勿用于任何商业用途)

——=== 访问 酷壳404页面 寻找遗失儿童。 ===——

CentOS 7 安装 Scrapy 记录

如何在Windows上安装Scrapy 之前的文章中已经讲过,这次的主题改为如何在Linux上安装Scrapy。这次安装选择的是CentOS 7 而没有采用Cent OS 6.7 主要原因是:CentOS 6.7 系统自带的Python是2.6版本,不能满足Scrapy的需求,如果升级成为Python 2.7可能会带来很多意想不到的灾难(先前已经踩过坑,T_T)。具体流程如下:

1、安装开发包组

yum groupinstall "Development Tools" -y

2、安装Scarpy 所需要的开发包

yum install -y python-devel openssl-devel libxslt-devel libxml2-devel

3、安装Python包管理工具pip

如果直接使用yum install python-pip进行安装会发生如下错误:

[root@localhost network-scripts]# yum install python-pip -y
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: centos.ustc.edu.cn
* extras: mirrors.aliyun.com
* updates: centos.ustc.edu.cn
No package python-pip available.
Error: Nothing to do

解决方案是先安装epel(EPEL是由 Fedora 社区打造,为 RHEL 及衍生发行版如 CentOS、Scientific Linux 等提供高质量软件包的项目):

yum -y install epel-release

安装完epel后再执行安装pip 即可,注意到系统自带的Pip不是最新版本的,还可以再升级下:

yum -y install python-pip
pip install --upgrade pip

4、使用Pip安装Scrapy

pip install Scrapy

至此,Scrapy在CentOS的安装就全部完成了,enjoy!

美国十年签证到手记

美国十年签证到手记

美国十年签证到手记

周一早上人还没到公司,就收到EMS快递员的电话,说有两份我的美国领事馆的签证快递,在前台要我签收一下。

美领馆的出签效率果然是高,上周三(8月10日)早上面签的,这三个工作日就把护照送到了。

今天来分享一下这一次我跟杨左一起准备美国签证的前后经历,没有干货,就是一些经验和tips,仅供参考。

之所以办美国签证,其实并不是为了去美国,而是为了去菲律宾,菲律宾允许持美国、申根、澳洲等发达国家有效签证免签入境7天,为了省点签证费用,就直接办美国签证了。从有这个想法到最后预约、面签前后也就一个多月吧。

上谷歌,以「美国签证 + 上海」等关键字搜索了一番,看了几篇其他人的面签攻略或者资料,想着,卧槽,怎么这么麻烦,怎么要准备这么多材料、各种证明、各种证,什么还要看面试官心情?什么还要看面试官肤色?什么还要挑时间?

问了几个去了美帝的朋友,有的朋友是独立申请的,也有通过旅行社办的。

在这里我先说结论:

不嫌麻烦就自己办,要不还是建议交给旅行社,价格上相差不太多。

后面来说为什么。

本着好学求知的精神,我登陆美帝移民局官网一探究竟,网站中文支持不错,按照说明步骤来操作就可以了。

http://www.ustraveldocs.com/cn_zh/cn-niv-ds160info.asp  

网站会要求先按照需求填写了DS-160表格。在这里还可以上传一张正方形的签证照片,系统会自动验证照片是否符合规格。

填写基本账号信息完毕之后,进入冗长的详细资料填写阶段,前后大概分了七八页,从基本资料、工作经历、教育经历、出境经历、旅途行程安排、犯罪违法情况等等填写了一大堆。

由于第一次填写,加上所有的资料都需要英文,不仅得把自己过去的学校、公司的名称、地址中英文都得翻译一遍,还得把准备第一次去美国的行程、入住酒店的信息和联络方式都填写一遍。

在这里请尤其注意,填写表格,网站有超时限制,过长时间没填完,就会登出,随时点击sava保存当前表格是王道。

不少人都是办下了签证,再做最后的行程安排,具体的入住酒店什么的,填表的时候只能边Google搜索边填,建议大家直接上IHG、SPG之类的国际酒店集团,选择你要去的美帝城市酒店,填酒店上面的英文联络方式就好了,省心,反正填了又不花钱,到时候也不是必须去。

填写完表格之后,会生成一个有唯一编号的DS-160表格,然后再缴费预约面试时间、地点。一开始会让你选择你要选择面签的城市,中国地区有北京、上海、广州、成都、香港等地。

我第一次选择的时候不知道怎么选择了香港。然后又无法修改城市,最后我通过在线contact us发送了一封ticket,描述了一下自己的情况,说由于mistake,错误地选择了interview location,please help me change it to Shanghai。过了一天就收到了邮件回复,说已经帮我把面签的城市改到了上海,在这里不得不赞一下美帝签证服务的这个服务系统。

其实还有另外一个方法不用麻烦人工服务,由于DS-160的单号都是唯一的,只需要重新填写一个DS-160申请表,拿一个新的单号重新注册和预约就好了,我是嫌这个麻烦,才发的ticket。

上面说了这么多,但是我并没有继续进行下去,因为我发现,美签在线支付费用要通过借记卡,在中信银行的在线商城扣款。我有招商和中国银行的借记卡,刚好找不到我中国银行借记卡的秘钥了,一想到招商在线网银支付的痛苦经历,我在这一步终止了。

由于我又不想去中信银行柜台,于是放弃自己填写DS-160自己预约渠道。

后来,找了一家比较大的淘宝旅行社(价格1298,比160美元贵了个200多块钱,就理解成服务费吧),把我跟妹纸的中文资料和护照信息交了过去,旅行社那边帮我们翻译了所有的资料,然后一条龙填写了DS-160表格,缴费和预约时间。

这个期间前后接到了三个电话,第一个电话是旅行社来跟我确认去美帝的日程,建议我把时间从明年春节改成今年的国庆期间,说明年春节时间有点太远了,签证官可能会以太早了为理由拒签,其他就没说什么问题了。

后来又来跟我确定了下妹纸的资料,问我们是不是一起去面签,大概想什么时候面签。

第三个电话,就是通知我们面签的时间,预约的就是8月10日上午9点,也邮件通知我们面签当天需要准备的材料、注意事项,联系人员等等。

一直到面签完毕,我们都没见过旅行社相关的人,面试那天由于我们到的比较晚,打不通旅行社人的电话(忙音),我跟妹纸就自己自己拿着资料和表格去面签了。

零.我们准备的材料

  • 护照(有今年的日韩签注记录)
  • DS-160表格和面签预约单
  • 行程单:随便做了一个洛杉矶-Vegas的十日行程
  • 户口本(我带了自己家的,妹纸没带)
  • 在职和收入中英文证明(公司HR有标准模板,盖公章)
  • 一年银行流水(中国银行大厅自助打印)
  • 个税缴纳单(上海税务局在线打印)
  • 学历证明(毕业证、学位证)

一.面签流程

美帝上海领事馆在南京西路梅龙镇商厦,原来就在妹纸公司旁边200米,我们头一天晚上分别用文件袋装好了自己的材料。

美国十年签证到手记

到达美帝领事馆楼下已经是早上的8点50分的样子,打不通旅行社送签的人的电话,想着资料我们也都有,就不管他们了(事后有个旅行社的未接电话),妹纸去附近存包(50元),在楼下指定排队处先领了一个通行证,然后过了外围的身着白色制服的保安检查,进入了大楼,坐电梯上到了美帝大使馆那层楼。

上楼之后不能携带任何电子设备,只能带装在透明文件袋的资料。

1) 初次安检:进门有位安保检查了我们的通行证(人手一张),在我们的手背上盖了一个荧光盖章,进入美帝领事馆办公室,迎面一面硕大的美帝国旗。
2) 预约单检查:一个工作人员扫描我们预约单上的条纹码,确认无误后,放行。
3) 护照检查:两个工作人员,分别检查了我们的DS-160表格,看了我们的护照,在我们的护照上面贴了新条纹码。

美国十年签证到手记

4) 安检:每个人领一个小篮子,把所有的东西都放进去,过安检机器。
5) 打指纹:在一个窗口,是个美国人,把护照贴在玻璃上指定位置,工作人员扫描了一下,一次记录左右手四根长指头,第二次记录左右上拇指。
6) 排队面签:

接下来就说下我和杨左的面签经历吧,大家都排在一个队伍里面,队伍还挺长的,前面目测有五六十号人,面签窗口大概开了10多个,分布在大厅的两侧,有一个安保在排队处安排分流,跟机场人工值机那很像。

观察了一下,面签官男女都有,中年和年轻人都有,有几个还挺帅的,黑白黄都有,应该是全部都会讲中文。

排了约20分钟的队,轮到了我,面试官是一个三十多岁的白人男性,面带微笑,先用中文跟我说了「你好」,我用中文回了「你好」,然后把护照从窗口递了进去,只递了护照。

签证官:有没有去过美国
我:没有
签证官:(键盘敲击......)
签证官:去做什么?
我:旅行
签证在:自由行么?
我:是
签证官:(键盘敲击......)
签证官:通过了
我:谢谢

对,就问了三个问题,什么资料和材料都没看,一分钟不到,就这么通过了。下一位是妹纸,这时候有另外一边队伍的人插队,我和妹纸尴尬地对望了一下。

插队的这位也是很快就通过了,看那嘚瑟的表情就知道,到我们家杨左上去了,据妹纸回忆,她的面签问题是这样的:

签证官:有没有去过美国
妹纸:没有
签证官:去做什么?
妹纸:旅游
签证官:一个人么?
妹纸:没有,跟我男朋友,就前面那个。
签证官:什么?没听清
妹纸:没有,跟我男朋友,就前面那个。
签证官:你来上海多久了?
妹纸:一年多
签证官:有居住证么?
妹纸:有,给(妹纸拿出准备好的居住证)
签证官:(键盘敲击......)
签证官:通过了

就这样,两个人的面试时间都不长,顺利地通过了面签,除了工资收入流水证明,均无提供存款、房产等其他证明材料。

在这里,我也不妄称专家过多解读,就说一下自己的一些理解吧:

  • 面签更多是对DS-160表格资料的一个确认,签证官对表格信息已经有了一个自己的预判
  • 务必诚实,真实填写自己的访美目的、收入、工作、学历、旅行经历等资料,诚实至关重要,要不可能留下污点进黑名单。
  • 有较多的境外旅行经历,应该可以大加分,妹纸只有今年的日韩、去年的港澳出境经历,发达国家的旅行经历属于一个重要考量因素,亚洲国家应该优先只看日本(旅行社也是这么说的)。
  • 建议别提前买机票,要不万一签证被卡,还是有点蛋疼。
  • 个人办和旅行办,最终还是看个人的基本资料条件和面签情况,旅行社在填表阶段、填写基本资料方面能够给一些建议。

美国十年签证到手记

从美领馆出来,我和妹纸来张自拍,哦耶,美帝,等我们来!机票已经买好啦!

HTTP 协议入门

HTTP 协议是互联网的基础协议,也是网页开发的必备知识,最新版本 HTTP/2 更是让它成为技术热点。

本文介绍 HTTP 协议的历史演变和设计思路。

一、HTTP/0.9

HTTP 是基于 TCP/IP 协议的应用层协议。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。

最早版本是1991年发布的0.9版。该版本极其简单,只有一个命令GET


GET /index.html

上面命令表示,TCP 连接(connection)建立后,客户端向服务器请求(request)网页index.html

协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式。


<html>
  <body>Hello World</body>
</html>

服务器发送完毕,就关闭TCP连接。

二、HTTP/1.0

2.1 简介

1996年5月,HTTP/1.0 版本发布,内容大大增加。

首先,任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。

其次,除了GET命令,还引入了POST命令和HEAD命令,丰富了浏览器与服务器的互动手段。

再次,HTTP请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。

其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。

2.2 请求格式

下面是一个1.0版的HTTP请求的例子。


GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*

可以看到,这个格式与0.9版有很大变化。

第一行是请求命令,必须在尾部添加协议版本(HTTP/1.0)。后面就是多行头信息,描述客户端的情况。

2.3 回应格式

服务器的回应如下。


HTTP/1.0 200 OK 
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84

<html>
  <body>Hello World</body>
</html>

回应的格式是”头信息 + 一个空行(\r\n) + 数据”。其中,第一行是”协议版本 + 状态码(status code) + 状态描述”。

2.4 Content-Type 字段

关于字符的编码,1.0版规定,头信息必须是 ASCII 码,后面的数据可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式,这就是Content-Type字段的作用。

下面是一些常见的Content-Type字段的值。

  • text/plain
  • text/html
  • text/css
  • image/jpeg
  • image/png
  • image/svg+xml
  • audio/mp4
  • video/mp4
  • application/javascript
  • application/pdf
  • application/zip
  • application/atom+xml

这些数据类型总称为MIME type,每个值包括一级类型和二级类型,之间用斜杠分隔。

除了预定义的类型,厂商也可以自定义类型。


application/vnd.debian.binary-package

上面的类型表明,发送的是Debian系统的二进制数据包。

MIME type还可以在尾部使用分号,添加参数。


Content-Type: text/html; charset=utf-8

上面的类型表明,发送的是网页,而且编码是UTF-8。

客户端请求的时候,可以使用Accept字段声明自己可以接受哪些数据格式。


Accept: */*

上面代码中,客户端声明自己可以接受任何格式的数据。

MIME type不仅用在HTTP协议,还可以用在其他地方,比如HTML网页。


<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- 等同于 -->
<meta charset="utf-8" /> 

2.5 Content-Encoding 字段

由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。Content-Encoding字段说明数据的压缩方法。


Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate

客户端在请求时,用Accept-Encoding字段说明自己可以接受哪些压缩方法。


Accept-Encoding: gzip, deflate

2.6 缺点

HTTP/1.0 版的主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。

TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。

为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。


Connection: keep-alive

这个字段要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段。


Connection: keep-alive

一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。

三、HTTP/1.1

1997年1月,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。它进一步完善了 HTTP 协议,一直用到了20年后的今天,直到现在还是最流行的版本。

3.1 持久连接

1.1 版的最大变化,就是引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive

客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。


Connection: close

目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接。

3.2 管道机制

1.1 版还引入了管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。

举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。

3.3 Content-Length 字段

一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是Content-length字段的作用,声明本次回应的数据长度。


Content-Length: 3495

上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。

在1.0版中,Content-Length字段不是必需的,因为浏览器发现服务器关闭了TCP连接,就表明收到的数据包已经全了。

3.4 分块传输编码

使用Content-Length字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度。

对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用”流模式”(stream)取代”缓存模式”(buffer)。

因此,1.1版规定可以不使用Content-Length字段,而使用“分块传输编码”(chunked transfer encoding)。只要请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成。


Transfer-Encoding: chunked

每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了。下面是一个例子。


HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

25
This is the data in the first chunk

1C
and this is the second one

3
con

8
sequence

0

3.5 其他功能

1.1版还新增了许多动词方法:PUTPATCHHEADOPTIONSDELETE

另外,客户端请求的头信息新增了Host字段,用来指定服务器的域名。


Host: www.example.com

有了Host字段,就可以将请求发往同一台服务器上的不同网站,为虚拟主机的兴起打下了基础。

3.6 缺点

虽然1.1版允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为“队头堵塞”(Head-of-line blocking)。

为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。如果HTTP协议设计得更好一些,这些额外的工作是可以避免的。

四、SPDY 协议

2009年,谷歌公开了自行研发的 SPDY 协议,主要解决 HTTP/1.1 效率不高的问题。

这个协议在Chrome浏览器上证明可行以后,就被当作 HTTP/2 的基础,主要特性都在 HTTP/2 之中得到继承。

五、HTTP/2

2015年,HTTP/2 发布。它不叫 HTTP/2.0,是因为标准委员会不打算再发布子版本了,下一个新版本将是 HTTP/3。

5.1 二进制协议

HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为”帧”(frame):头信息帧和数据帧。

二进制协议的一个好处是,可以定义额外的帧。HTTP/2 定义了近十种帧,为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。

5.2 多工

HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了”队头堵塞”。

举例来说,在一个TCP连接里面,服务器同时收到了A请求和B请求,于是先回应A请求,结果发现处理过程非常耗时,于是就发送A请求已经处理好的部分, 接着回应B请求,完成后,再发送A请求剩下的部分。

这样双向的、实时的通信,就叫做多工(Multiplexing)。

5.3 数据流

因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。

HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。

数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。

客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。

5.4 头信息压缩

HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如CookieUser Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。

HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzipcompress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

5.5 服务器推送

HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。

常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。

六、参考链接

(完)

文档信息

Category

Archives