中国互联网20年简史(1998-2018),告诉你本质是什么、规律是什么

我先说说互联网三大支柱:

1、内容:新闻&文学、音乐&视频

2、社区+内容

3、游戏

4、电子商务

我们来简单回顾一下中国互联网20年。咱们先从1998年开始。

一、1998年:内容门户元年

1998年2月,张朝阳正式成立搜狐。给中国产业带来了VC风险投资、CXO职业经理人团队,让中国老百姓认知了中国互联网。

1998年,四通利方和北美华人网华渊网合并,成立新浪网。给中国产业带来了并购、创始人被踢出团队。

1997年,网易成立。1998年推出网易免费电子邮件服务。

显然,这是内容门户之年。

虽然1998年腾讯也成立了,但显然大家都没注意到它。但最后四大门户是:搜狐、新浪、网易、腾讯。

还有一家公司成立,那就是在线网络游戏公司:联众,出自希望公司UCDOS软件团队。

你看,内容门户+BBS论坛社区+IM+游戏,在20年前,就同时出现了。中国互联网主航道,都基本出现。

二、1999年:电子商务元年

内容门户大热到极点。连联想都做了一个FM365。更别说还有中华网、TOM网、多来米这些富家子弟玩的。这些显然都是后知后觉了。

1999年11月,当当B2C成立,标品卖书,客单价也低,正好做启蒙。1999年,阿里巴巴B2B也成立了,搞黄页,帮助中国小商品制造出口走向国际。

1999年还成立了一家当时没人知道的公司:携程。

1999年还成立了一家公司:51job,网上找工作。其实招聘的本质是:黄页信息,只不过这个黄页不是企业信息,而是个人简历信息。

这是中国电子商务的开始。他们真是先知先觉。

三、2000年:内容门户上市年

网易、搜狐、新浪都在纳斯达克上市。这才短短3年时间。

2000年1月,百度成立。

四、2001年:移动手机元年

美国互联网投资泡沫破裂,也影响了中国。很多后来进入者都纷纷转型去开发企业软件,因为他们熟悉互联网、熟悉当时火热的Web开发技术和JAVA开发技术,所以他们一开始就做供应链互联网平台。当时中国企业软件商还在纷纷用VB/PB/DELPHI开发局域网企业内部管理软件呢。

但是在前几年互联网资本的推动下,基础设施:通信&数据传输网络也在迅猛发展。诺基亚在这一年市值逼近2500亿美金,中国出现国产手机热,以波导为代表,IT厂商联想也介入进来,家电厂商海尔也介入,电话座机厂商步步高(Vivo和Oppo的母公司)也介入。

五、2002年:移动手机内容SP元年

2002年,中国移动和中国联通的手机终于能短信互通了。好不容易2000年上市的三大门户都熬的受不了,想寻找到立刻变现的业务。

彩铃、短信报热。网易首先抓住这个机遇(嘿嘿,大家可以另外寻找网易和张静君和广州电信局的渊源)。中国互联网企业做SP业务开始了,尤其是把网上的新闻和段子通过短信传播。

六、2003年:网络游戏元年

2003年7月,盛大公司发布传奇世界游戏,引发了中国网络游戏热。随后,九城、完美时空、巨人等等公司跟进,造就了中国很多赚的盆满钵满的网络游戏公司。这个行当也给中国积累了大量的产品经理、制作人、美工人才、音效人才、3D技术、网络技术。

七、2004年:中国互联网第一波集中上市收割年

2004年,移动手机内容SP厂商:空中网、掌上灵通网,上市。

2004年,垂直金融内容门户公司:金融界,上市

2004年,社区+IM+游戏厂商腾讯上市。

2003年12月(相当于2004年了吧),中国电子商务第一个公司:携程,上市。携程。从1999年中国电子商务开始元年,到2003年,这才短短4年时间。

2004年,泛电商人才招聘网:51job上市。

2004年,网上卖机票电商网:E龙上市。

2004年,网络游戏厂商:盛大,上市。

从1998年算来,到2004年,6年时间,中国互联网开始了第一波收割热潮。

八、2005年:Web2.0社区内容元年

2005年,超女最火的一届出现:李宇春、张靓颖、何洁。大众用短信投票引爆全国。这是民众的、互动的狂欢。

2005年,新浪博客发布。

2005年3月,豆瓣成立。这是一个点评的网站。

2005年12月,58同城成立,这是一个个人黄页发布的网站。

额外,搜索引擎公司:百度,在这一年上市了。

七、2006年:网络视频内容元年

2006年,六间房视频网成立。2006年,李善友的酷六网成立。2006年,优酷网成立。2006年,Google并购Youtube网。

另外,2005年4月,土豆网成立。2005年,迅雷公司正式成立。2005年,VeryCD(电驴下载)公司正式成立。这都是和视频电影的崛起有关联的。

过去大家只能看文字图片内容网站,做图片钻展广告。现在有了更直观的视频网站,而且每部电影都可以贴片做广告了。

但是并不代表文字内容网站失落,相反,中国网络文学崛起,你看:2006年,天下霸唱开始写鬼吹灯引爆盗墓类小说、2006年当年明月开始写明朝那些事儿引爆写史类小说,2006年月关开始写回到明朝当王爷引爆穿越类小说。

2006年,其实还有一个大混战,就是楼宇广告大战。成立于2003年的分众传媒,2005年上市,2006年并购了聚众传媒、框架传媒。

八、2007年:电子商务高速成长年

2007年,阿里巴巴B2B业务在香港上市。

但是大家也别忘了,2007年8月,中关村一个经营了快10年的拥有11家线下店铺IT硬件批发零售商,融了一笔钱,开始关闭自己的线下店,专注高速发展线上电商自营零售,那就是京东。

2007年,Yes!PPG成立,主打自创品牌的男士商务休闲服装。2007年,模仿Yes!PPG的凡客诚品也成立了。这是中国自创品牌的电子商务公司,集:研发设计、供应链采购、委托加工、质量控制、商品电商零售、仓储物流配送于一体。

2007年,也是中国快捷酒店大战的一年。如家、汉庭、锦江之星、7天、莫泰、格林豪泰、布丁、桔子酒店…,好多好多。

悄悄另外说一句:2007年,iPhone上市了,大内存、高速CPU、高速WIFI网络、大屏幕、多点触摸输入操作,这几乎是和过去的智能手机有天壤差别:小内存、小屏幕、GPRS联网、笔触输入或键盘输入。中国移动互联网暗示着要大规模爆发了。

九、2008年:智能手机元年

2008年,是中国互联网的十周年。但是这一年也暗示着,中国PC Web互联网即将开始走向最高峰,最高峰也意味着下一个时代已经在悄然启动。

2008年,Google正式发行Android操作系统。

2008年,Apple发布iPhone3G手机,最最关键的是,智能手机的高利润盈利模式、流量口模式出现了:App Store。想想百度收购91,其实也想占领智能移动互联网的入口,没想到独立的应用商店根本不存在活路,全被智能手机厂商在底层釜底抽薪了,人家有小米应用商店、华为应用商店…,全是硬件+软件一体化的。

2008年,山寨手机热啊。在联发科一体化MTK模组的支持下,在华强北电子零件集散批发、深圳电子代工场云集的支撑下,中国人制造手机的门槛被放到最低。

十、2009年:交战年

2009年,新浪微博发布显然是最显眼的。随后,各大内容门户网站纷纷发布类微博产品服务。微博,120个字,类似短信使用体验却可以带图片(比短信好),可以关注名人还可以评论互动(不像QQ得双向关注),也可以随手转发。

除了微博这种类互联网手机上的多媒体短信产品大战,这一年整个互联网界都不平静。

淘宝发布购物搜索,屏蔽百度爬虫。当然,微软也发布了Bing搜索引擎来PKGoogle搜索引擎。

腾讯和搜狗针对输入法进行诉讼。因为输入法在用户需求探知、弹窗引流、输入汉字导流方面具有很高的入口杀伤力。

网络游戏《魔兽》的代理运营权,也在九城、网易之间拉锯。

还有2008年很火的基于QQ社交网络关系的页游:偷菜,开心网和千橡开心网也进行了诉讼。

为什么2009年如此不平静?就是因为PC Web互联网进入成熟期,产业要开始高度集中,要进行整合,不可避免要咔咔作响。

2009年,中国三大运营商均获得3G牌照,移动互联网眼看着眼看着要来临了。

十一、2010:电商爆发年

2010年大家最记忆犹新的肯定是百团大战,大量团购网站出现,尤其以2010年3月美团成立为标志。中国电子商务:衣食住行,衣,有淘宝;食开始了,就是这些团购网;住,有曾经的如家快捷酒店大战,也有58的租房二手房黄页广告聚焦房产行业大战;行,有过去的携程、E龙、同程、去哪儿大战。除了衣是实物零售业外,其他食住行都是服务电商业,即:在网上吸引消费者流量,在网上获得优惠折扣,在网上下订单,甚至在网上进行支付,然后在线下进行到场消费。

2010年,在衣这个事情上,还有一个轰动的事,那就是淘宝双十一热。但这已经其实是第二届了(第一届是2009年双11),但就如超女一样,也是第一届举办完了大部分人都不知道,第二届才引爆。双11对于淘宝的意义非常大。而京东,在2010年也迎来了爆发式增长:开放POP平台、一线城市极速达、收购网银在线介入金融业务。而且京东主动发起了图书大战,直指当当老大哥(当当可谓是中国互联网最早的电商零售)。还有一家发源于手册邮寄购买最终爆发于电商的服装零售公司:麦考林,也在2010年上市了,成为了第一家上市的电子商务零售公司(2007年阿里巴巴B2B业务上市。)

1999年,中国电商元年;2007年,中国电商成长年;2010年,中国电商爆发年。

当然,在PCWeb纯互联网领域,2010年也发生了一件非常大的事情,就好像两个黑洞碰撞一样巅峰对决,那就是3Q大战。2010年11月21日,在工信部、网信办的协调下,两个公司达成和解,不互相封杀卸载对方的软件。中国PC 互联网终于走到了尽头。就好像红巨星要爆炸要产生超新星是一样一样的。从1998年开始的PC Web互联网,走到了2008年智能手机元年,2009年互联网产业整合交战,最终在2010年3Q大战最高巅峰对决中收场。

再想想中国移动互联网,2008年是智能手机元年,今年是2018年,也十年了,今年的大战是腾讯集团和今日头条的大战。相信到2020年,也会如超新星一样,那时候是什么互联网呢?已经有了ADSL宽带PC Web 互联网和4G 移动 App互联网,难道那时候在5G的引导下,会出现万物互联网?

4G移动App互联网,以移动智能手机为主产业,那5G万物互联网,什么是主产产业呢?难道是智能汽车?

十二、2011:中国移动互联网元年

这一年,有两个重要级产品出现,一个是智能手机:小米和MIUI OS出现,一个是原生移动IM:微信出现。

智能手机硬件、Andriod操作系统、应用商店、IM通信,这种组合层次颇值得人寻味。在万物互联网时代会不会出现的最初超级应用也是这样?

其实早在2G GPRS时代,在2008年,手机QQ已经很多人使用了,但是微信出现了,手机QQ没落了。微信的出现正好和iPhone成为智能手机事实标准是同步的。从iPhone开始,过去手机是五花八门各种样子各种功能,尤其在山寨手机之时到达最高潮,然后在iPhone带动下,全世界的手机都变成一模一样的大体模样了。也就是说,都是大屏幕、无键盘。微信的崛起第一步就是:语音消息、手机通讯录导入、摇一摇周边。你看,全是原生应用了手机的独特特性。大家在思考万物互联网的时候也应该这样思考,要充分应用硬件的独特特性,而不是把大象装在冰箱里(比如很多人把企业管理软件精简功能做成App)。

十三、2012年:中国移动互联网发展年

这一年,中国手机网民数量超过了电脑上网网民数量(其实2013年中国政府才要求运营商强力推4G)。

这一年,中国移动互联网高速发展,大家都纷纷把自己的PC Web互联网的功能翻新成App版本。

华为、锤子也正式宣布进入智能手机领域。360和海尔也联合推出超级战舰手机。就连腾讯也谨慎的做了一个手机ROM。大家纷纷想从智能手机硬件、智能路由器和DNS、OS、应用商店、通信IM超级APP,一层层地釜底抽薪。

十四、2013:中国移动互联网爆炸年

3年啊,同志们。太快了,怪不得劳模雷军说:现在就连睡觉都觉得是浪费。

这一年,小米开始构建自己的智能产品生态,发布了好几款智能产品。这一年,乐视智能电视发布,乐视开始引爆江湖。

在这一年有两个关键事件决定了这一年是移动互联网爆炸年。一个是微信发布了游戏流量入口、打飞机小游戏狂潮掀起了移动游戏App的热潮。移动互联网,怎么能够少了游戏这一个半边天呢。微信在这一年还发布了公众号。没有媒体人的卷入,就不可能有大影响力大声音。微信也是在这一年狂发展的。

另外一个大事件就是,也就是从这一年开始,BAT们都开始做好自己的主流超级流量App,大力发展Open API开放平台,大力做投资并购。中国移动互联网为什么发展的这么快,关键就是有三大要素:超级流量、Open API和平台、资本投资和并购进入山头帮派时代。同志们,这句话要标红啊。这是过去中国互联网界从未有过的事情啊。这是中国互联网的并购年,其中最大的收购案就是百度以18.5亿美金收购91无线。

十五、2014:中国企业服务元年

在这一年,中国电商出现了一件大事:京东、阿里纷纷上市。京东和阿里占据中国线上B2C零售80%市场份额,构成了真正的双子星结构。这种市场结构,意味着这个市场已经成为寡头市场。现在再进入这个市场,不可能再出现第三巨头了,从第三名到最后一名,所有加总才能占据最多20%市场。从目前来看,就连拼多多这种拼团模式、云集微店众包销售模式,也只能成诸侯而不能成王。

虽然说,云计算创业三小龙:Ucloud、七牛、青云,都是2010-2011间成立的。但是,中国企业服务投资规模第一波热潮却真正来自2014年。其实不说2006年Amazon发布AWS,就说阿里云,也是在2009年10月写下第一行代码,2012年做天猫聚石塔项目,2013年换帅胡晓明开始高速发展。而中国IaaS云计算的高潮,还要等到2016年,那一年,所有互联网大佬、所有中国系统集成商大佬都已经进入IaaS公有云和私有云的市场。不过很多人却还后知后觉,直到2015年中国企业服务投资最高潮,很多人才匆忙杀入了这个行业,才匆忙升级要做SaaS软件。

这一年还有件事,就是菜鸟网络在这年成立了。菜鸟网络不搞仓库不买卡车不跑运输不招业务人员,但是菜鸟网络凭借淘宝天猫的订单流量、凭借自己的大数据建模技术,来做到智能的仓储物流调度,抽取中间的调度佣金。这本质上是电商+企业服务的混合体。

这一年还有件事,是滴滴的快速崛起。滴滴后来被人们笑话段子都演变成了滴滴模式(拼多多拼团也是种模式、团购秒杀倒计时也是种模式),什么滴滴打人、滴滴代喝、滴滴代嫁等等,哈哈哈。但是,滴滴代驾、滴滴拼车业务真的出现了。滴滴的核心是:根据地理位置(智能手机独特特性)、根据业务大数据和用户画像,智能匹配最合适的打车人和出租车,抽取中间的调度佣金。这本质也是电商+企业服务的混合体。

也就是说,智能调度匹配抽佣金,这个模式,会在中国业务+IT服务的各行各业中,都会形成落地的业务场景。这就是一种经过验证的以技术为本的商业模式。这个模式,非常值得中国企业服务商去探索借鉴思考。

十六、2015:中国互联网金融元年

这一年,在中央的大众创业万众创新的推动下,互联网金融开始热潮。当然,中国电子商务要高速发展,没有金融的支撑也是不能更快更大的发展。

所以这一年,P2P热、众筹热、消费贷热、供应链金融热都起来了。

但更突出的是:微信支付和支付宝支付开始大战。大家纷纷通过各种扫街、发起补贴活动,到处贴二维码,可以扫码支付。现在,就连买菜买鸡蛋夹肉饼,都可以用手机扫码。这种便捷性是全世界最领先的。

十七、2016年:智能元年

这一年,直播热崛起。但是这种直播和过去最早YY的直播还不一样。现在的直播最关键应用了实时美颜技术、虚拟AR技术。

这一年,从支付宝AR找福字、美颜App自带兔子耳朵虚拟表情开始,就发现今年的不一样了。那就是现实和虚拟的实时结合。

所以这一年,也带动了AR、VR设备热。也带动了人工智能技术热,先从人脸识别开始。

直播热从娱乐很快扩展到了电商,从虚拟送礼盈利走向推荐商品带货盈利。这也造就了2016年的微商热。这不同于过去的微商拼命加5000人拼命加群拼命发朋友圈鸡汤发微商广告的模式。这一年的微商都在实时美颜直播技术中统统成为了网红。

直播打赏热(这里也有上一年移动支付大战红包大战的功劳),也渐渐带动了另外一个正经事:知识网红(如罗振宇)+知识付费(如得到)。

这一年,还出现了共享单车大战,最后连颜色都不够用了。这里面最有名的论战就是马化腾和朱啸虎的言战,焦点是谁能笑到最后。马化腾认为是一定要是智能设备,如智能车锁,这显然是技术派的看法。而朱啸虎代表运营派,也就是说:最成熟的产品和消费习惯,最广阔的市场,用资本轰开。现在,朱啸虎的OfO陷入尴尬境地,朱啸虎后来都暗示服了软,显然,智能才是核心。

十八、2017年:新零售元年

2017年说什么热,那必须是新零售。新零售的本质是用智能传感设备、人工智能技术,实现线下数据收集和线上电商是一样的效果。大家切记切记。

虽然说,有人把新零售看做是线下,用正规企业运营方法再重做一次,就如同当年如家他们用资本+企业标准运营管理方法重塑中国快捷酒店业一样。

技术派:无人零售商店、无人货架&货柜、智能购物车、智能称重台、人脸识别进门、人脸识别自动支付

运营派:生鲜、生鲜+餐饮堂食、连锁便利店、中央厨房供应链….

十九、2018年:

2018年,中国互联网金融热已经过去了3年。今年卷土重来的是:区块链。创建X币项目、发币上交易所市,成了主流割韭菜模式。看不清看不清。

在去年直播热、直播技术、直播打赏普及成熟的基础上,快手、抖音短视频热崛起。但是这种短视频又和过去的移动视频热不一样。因为除了技术流畅、打赏付费习惯成熟外,现在抖音又多了附近、朋友、互动。这简直是下一代社交网络的潜力啊。怪不得腾讯今天上半年从收购到打击抖音到内部赛马做了N多短视频App,根源就在于此。

我过去就说过,QQ发源于台式机拨号上网文字时代,微信发源于智能手机4G上网语音时代,那么下一代社交网络工具一定是基于万物互联5G上网视频时代。

从2008年智能手机元年开始算起,今年也已经十年了。智能手机移动互联网时代也要高潮地结束了。今年,小米也要在港交所上市了。

一个时代即将结束(还有2年最后的两个黑洞大碰撞,我猜是腾讯集团和今日头条集团),那么我们在今年,确实应该多静下来思考思考,几个好友坐下来重新回归历史一片空白该想想了、放开脑洞发散性讨论讨论了。

下一代主流硬件是什么?下一代主流OS是什么?

下一代主流社交网络工具是什么?下一代搜索是什么(是视觉识别和语音交互吗)?

下一代内容是什么样子的?比如说新闻、文学、视频、音乐…。

下一代游戏是什么样子的(是ARVR吗)?

下一代电子商务是什么样子的?下一代后端企业服务是什么样子的?

这里边,有你吗?

下一代商业模式的核心要素是什么?除了:流量、资本、技术和数据以及开放平台外,还有什么新的要素?

from:https://mp.weixin.qq.com/s/X195WPlHz6IyMyg-lpc9Yg

应用程序开发: Cordova vs ReactNative vs Xamarin vs DIY

标签: React Xamarin

你还在通过编写本地的iOS或Android代码来创建移动应用程序吗?对于那些平台特定的编程语言和工具、技能集问题、程序有非常具体的需要或者只是无知,或许这才是永远的爱。该是我们重新审视移动应用程序开发、选择合适的工具和框架集的时候了,以使我们的工作有更高的投资回报率(ROI)和更快的开发速度。

我和周围的很多开发者聊过,他们绝大多数都不喜欢用本地iOS(Swift、object C)、android(java)或者Windows(.Net)特定的编程语言和工具开发移动应用程序,因为他们的程序设计目标是多平台。原因在于本地开发需要每个平台对应自己特定的技能集,通常需要更多的开发努力。

几个月前,我们开始使用React Native,必须承认对于应用程序(app)开发来说,它的功能非常强大,使用起来也很愉快。自从Facebook用React native实现了对Android的支持起,我们基本上接受了它。尽管如此,React Native并非独一无二,还有另外一些很棒的选项,比如Xamarin。对于快速移动应用程序开发来说,Xamarin是一种功能最丰富、易于创建和使用的平台。

我在这里不会涉及所有可选的移动应用程序开发平台,只是分别用一个有代表性的平台来说明不同的开发方法,以便让你理解每一种开发方法的概念和方法论。

移动应用程序开发-平台的选择

说起移动应用程序开发,自然界中有许多平台和工具可以使用。在过去的几周里,我对各种开发方法进行了评估,并得出结论,有五种开发方法可供选择,列举如下:

  • 本地开发
  • Cordova :基于混合模式移动应用开发(Hybrid app)
  • 使用React Native进行移动应用程序开发
  • 使用Xamarin进行移动应用程序开发
  • DIY (Do It Yourself)工具:最后但并非最不重要

所有的工具都可以划归到上面提及的某一类中,它们提供了不同的功能集,需要特定的技能集来进行移动应用的设计与开发。在长期的移动应用开发策略中,首先选择正确的工具/平台是非常关键的因素。

选择哪个移动app开发更好?

选择不同的本地代码开发具有他们自己的优势和背后的道理。没有任何一个工具或者方法注定就是赢家,由于它依赖多种因素。在选择一个特定app开发平台或者方法最重要的因素依赖下面的关键点——

  • 个人或者开发团队的技能
  • app独一无二的需求
  • 目标用户划分
  • 个人或者组织的长期策略视野

如果你只是在一个特定平台开发apps,那使用native(swift,objective c 开发ios,java开发android)是最佳选择,因为你可以获得最佳性能、最新的APIs和工作特征。

你只是选择一个平台,那么,不必担心代码的复用。偏离本地主要理由是开发团队的技能,虽然不是唯一的一个。

让我们看看本地开发不同选择的替代方面。

基于Cordova的移动App开发

混合App开发使用纯的JavaScript、HTML和CSS ,它是最容易和最流行的开发方法之一,它在过去的网络开发中处于优势地位。有大量的框架采用了古老的纯的JavaScript和CSS,这些框架可以让你很轻松地进行移动App开发;其中的一些框架包括Ionic, kendo UI和 jQuery Mobile。

当然,你也可以选择不使用已有的框架,而是使用纯净的JavaScript、HTML和CSS,从头开始构建你的App部件。然而,使用像 Ionic、Kendo UI、 jQuery Mobile、 Onesen UI或者其它任何一种建立好的框架都会使你的开发时间以指数方式减少。

你或许想要查看这篇热门文章 – 最好的混合App开发框架

你的App如何访问硬件组成呢?

Cordova该要出场了。它提出了统一的JavaScript API,使用这些API可以访问像摄像头和加速度传感器一类的设备功能,在Android、iOS和Windows这样的几乎所有平台上都有加速度传感器。你一旦准备好App,就可以使用Cordova对其进行编译,Cordova会将App连同特定的JavaScript、CSS和HTML一起打包进平台特定的容器(webview)中。该容器在你的程序和硬件组成之间通过统一的JavaScript API架起了一座桥梁。

你得到的最大好处是只需要开发和维护单一的代码库,还有就是,如果你已经是一名Web开发者,就无需学习任何新技术了。

这里需要注意的关键点是程序运行在webview容器中,而并非运行在硬件本地,这使得它在性能上比原生Android程序或原生iOS程序要差。但是,所有的App并不都需要超级性能,对此你要首先做出权衡和决定。

Cordova遵循Apache许可证,自由且开源,它由Apache软件基金会发布。要阅读更多有关Cordova的内容可访问cordova.apache.org

使用React Native进行移动App开发

对于快速移动程序开发来说,React native相对较新,但却是一种优秀的开发方法,iOS和Android均可以使用。最近已增加了对于Android的支持。React native是来自于Facebook的开源框架,用来开发原生iOS和Android App。

尽管React Native是市场中的新成员,但是在全球范围内许多开发者和组织已经开始使用它进行跨平台移动App的开发,有一些App范例,比如SoundCloud Pulse、 Discovery VR、Facebook Ads Manager、 Bit Wallet、 Squad、Myntra和Running。

React native同样基于JavaScript,但只是纯的JavaScript、HTML5和CSS没有太多帮助,你需要投入一些时间学习更多的东西。你需要理解React,它是facebook为了开发网络程序于2013年发布的框架,React native是React本身的扩展,它们使用了同样的开发理念。

除了React框架,你还需要理解JSX,JSX是对ECMAScript进行了语法扩展的类XML。一旦你对JSX上了手,那么编写React native UI组件将变得绝对轻而易举。你也需要使用Xcode,它是用来构建Android版本App所需的iOS模拟器和命令行工具。另外,掌握程序架构框架的知识将有助于组织并加速App的开发,这些知识比如有Flux和与之相关联的类似Redux和Reflux这样的包。

React Native和Cordova或PhoneGap之间的比较

在Cordova中基于混合程序使用HTML和JavaScript组件开发的UI运行在Android和iOS平台的webview(内嵌在浏览器中)容器中。在React Native中同样如此,UI是用JavaScript react组件(JSX扩展)编写的,只不过每个React native UI组件和iOS以及Android的原生UI组件都是对应的。因此,用JavaScript编写的组件要转换成原生组件。这样我们就拥有了访问底层平台原生组件的JavaScript代码接口。

例如:创建标签-在react native中用TabBarIOS组件实现iOS中的UITabBar,用DrawerLayoutAndroid组件实现Android中的抽屉(Drawer)效果。

上面的例子也说明使用react native在Android和iOS之间的代码重用并非纯粹的100%,但是根据开发内容的不同,能够达到85%-100%这样的目标。

使用react native最大的好处在于仅仅使用JavaScript就可以同时开发iOS和Android版本的App。理念就是-“仅学习一次,就可以编写任何平台,并达到代码重用的最大化”。

更多有关React Native的知识可访问 react native

使用Xamarin进行移动app开发

Xamarin是用于构建原生移动App的另一平台,它是用于构建App的最有用的平台之一。使用Xamarin,可以通过C#语言编写原生Android、iOS、windows和Mac程序。

Xamarin的开发理念和React native基本一样,但是对技能集的要求有了彻底的改变,因为不再使用JavaScript,而是要使用C#和Microsoft工具。代码也不能100%重用,但80%的目标可以很容易达到。

使用Xamarin编写程序不是最容易的,但是可以让你编写出高性能的移动程序。用C#编写代码时,Xamarin编译器将代码编译成iOS、Android或者Windows Phone各自平台的原生包。对于iOS,会将代码直接编译成ARM汇编代码,所以它是纯碎的原生程序。

Xamarin.forms是由Xamarin团队最新推出的又一个功能,使用它开发原生的Android、iOS或Windows程序可以达到100%的代码重用。这些界面的UI控件在运行时会映射成原生控件,因此100%的代码重用是可能的。尽管它没有涵盖全部的原生控件,但已涵盖编写程序时要用到的90%的控件。

Xamarin是Microsoft收养的孩子。Microsoft最近收购了Xamarin,自此以后,Xamarin的用途会进一步增强,更多的功能会比以前增加的更快。

C#开发者可以自如地使用其中一个最高级的IDE-visual studio进行程序开发。Mac用户也可以使用具有相同丰富特性的Xamarin studio进行开发。

了解更多有关Xamarin的信息可以访问xamarin

使用DIY的APP构建工具进行移动APP开发

你自己的工具不够创新或者无法开发新的应用程序,但是,在短期内这些非常有利于从应用市场获取一个app。这些工具封装了大量模板,正在等待在苹果的应用市场或者谷歌play发布。

这些工具大多数是基于云app开发平台,保障你不用担忧要建立你的系统来构建移动应用。你自己的工具提供直观的app接口就可以用来构建app,不用任何先前的开发经验。

你可以选择一个app模板,以你的方式去自定义和配置他,全部使用你自己的设置。个人与小企业使用这些工具来创建移动apps, 并且更加快速推向市场。

UI/UX设计师总是依赖程序员来实现他们梦寐以求的app以推向市场,但是当今时代,UI/UX设计师可以使用拖拽和摆放工具来创建移动apps,向开发者边缘化。图像设计师可以采用app模板来创建和混合出漂亮好看的图形,使得app看起来独一无二(虽然不仅如此)。品牌与品牌之间的联系具体的图形和颜色,使得app独一无二。

在这个节奏快速的世界,当你的目标是创收,那它可能不总是专注于创新和创造,从零开始建立应用程序,使用现有的app模板来订制您的或者您的客户的需求,这样可能会更加高效。

你可能想查看这篇流行的文章-Top 10 DIY mobile app makers.

结论

应用开发和许多平台的选择都有很多的方法论,没有哪个是通用的。

很多开发者就是爱 Java ,并且持续用 Java 开发安卓应用,不认为有什么其他的选项,同样在 Objective-C 的开发者中也这样。不可否认,本地 app 开发带来的最佳性能和流畅体验。

随着像 Ionic,Onsen UI, Intel XDK 和 Sencha Touch 这些的混合框架的出现, Web 开发者变成移动开发者将不会有任何困难。所有这些框架的处理几乎都是与 JavaScript,CSS 和 HTML 相关,并且支持几乎所有的移动平台。

from:https://www.oschina.net/translate/mobile-app-development-cordova-vs-react-native-vs-xamarin

微服务化之缓存的设计

本文章为《互联网高并发微服务化架构实践》系列课程的第五篇

前四篇为:

微服务化的基石——持续集成

微服务的接入层设计与动静资源隔离

微服务化的数据库设计与读写分离

微服务化之无状态化与容器化

在高并发场景下,需要通过缓存来减少数据库的压力,使得大量的访问进来能够命中缓存,只有少量的需要到数据库层。由于缓存基于内存,可支持的并发量远远大于基于硬盘的数据库。所以对于高并发设计,缓存的设计时必不可少的一环。

一、为什么要使用缓存

为什么要使用缓存呢?源于人类的一个梦想,就是多快好省的建设社会主义。

多快好省?很多客户都这么要求,但是作为具体做技术的你,当然知道,好就不能快,多就没法省。

可是没办法,客户都这样要求:

这个能不能便宜一点,你咋这么贵呀,你看人家都很便宜的。(您好,这种打折的房间比较靠里,是不能面向大海的)

你们的性能怎么这么差啊,用你这个系统跑的这么慢,你看人家广告中说速度能达到多少多少。(您好,你如果买一个顶配的,我们也是有这种性能的)

你们服务不行啊,你就不能彬彬有礼,穿着整齐,送点水果瓜子啥的?(您好,我们兰州拉面馆没有这项服务,可以去对面的俏江南看一下)

这么贵的菜,一盘就这么一点点,都吃不饱,就不能上一大盘么。(您好,对面的兰州拉面10块钱一大碗)

怎么办呢?劳动人民还是很有智慧的,就是聚焦核心需求,让最最核心的部分享用好和快,而非核心的部门就多和省就可以了。

你可以大部分时间住在公司旁边的出租屋里面,但是出去度假的一个星期,选一个面朝大海,春暖花开的五星级酒店。

你可以大部分时间都挤地铁,挤公交,跋涉2个小时从北五环到南五环,但是有急事的时候,你可以打车,想旅游的时候,可以租车。

你可以大部分时间都吃普通的餐馆,而朋友来了,就去高级饭店里面搓一顿。

在计算机世界也是这样样子的,如图所示。

越是快的设备,存储量越小,越贵,而越是慢的设备,存储量越大,越便宜。

对于一家电商来讲,我们既希望存储越来越多的数据,因为数据将来就是资产,就是财富,只有有了数据,我们才知道用户需要什么,同时又希望当我想访问这些数据的时候,能够快速的得到,双十一拼的就是速度和用户体验,要让用户有流畅的感觉。

所以我们要讲大量的数据都保存下来,放在便宜的存储里面,同时将经常访问的,放在贵的,小的存储里面,当然贵的快的往往比较资源有限,因而不能长时间被某些数据长期霸占,所以要大家轮着用,所以叫缓存,也就是暂时存着。

二、都有哪些类型的缓存

当一个应用刚开始的时候,架构比较简单,往往就是一个Tomcat,后面跟着一个数据库。

简单的应用,并发量不大的时候,当然没有问题。

然而数据库相当于我们应用的中军大帐,是我们整个架构中最最关键的一部分,也是最不能挂,也最不能会被攻破的一部分,因而所有对数据库的访问都需要一道屏障来进行保护,常用的就是缓存。

我们以Tomcat为分界线,之外我们称为接入层,接入层当然应该有缓存,还有CDN,这个在这篇文章中有详细的描述,微服务的接入层设计与动静资源隔离

Tomcat之后,我们称为应用层,应用层也应该有缓存,这是我们这一节讨论的重点。

最简单的方式就是Tomcat里面有一层缓存,常称为本地缓存LocalCache。

这类的缓存常见的有Ehcache和Guava Cache,由于这类缓存在Tomcat本地,因而访问速度是非常快的。

但是本地缓存有个比较大的缺点,就是缓存是放在JVM里面的,会面临Full GC的问题,一旦出现了FullGC,就会对应用的性能和相应时间产生影响,当然也可以尝试jemalloc的分配方式。

还有一种方式,就是在Tomcat和Mysql中间加了一层Cache,我们常称为分布式缓存。

分布式缓存常见的有Memcached和Redis,两者各有优缺点。

Memcached适合做简单的key-value存储,内存使用率比较高,而且由于是多核处理,对于比较大的数据,性能较好。

但是缺点也比较明显,Memcached严格来讲没有集群机制,横向扩展完全靠客户端来实现。另外Memcached无法持久化,一旦挂了数据就都丢失了,如果想实现高可用,也是需要客户端进行双写才可以。

所以可以看出Memcached真的是设计出来,简简单单为了做一个缓存的。

Redis的数据结构就丰富的多了,单线程的处理所有的请求,对于比较大的数据,性能稍微差一点。

Redis提供持久化的功能,包括RDB的全量持久化,或者AOF的增量持久化,从而使得Redis挂了,数据是有机会恢复的。

Redis提供成熟的主备同步,故障切换的功能,从而保证了高可用性。

所以很多地方管Redis称为内存数据库,因为他的一些特性已经有了数据库的影子。

这也是很多人愿意用Redis的原因,集合了缓存和数据库的优势,但是往往会滥用这些优势,从而忽略了架构层面的设计,使得Redis集群有很大的风险。

很多情况下,会将Redis当做数据库使用,开启持久化和主备同步机制,以为就可以高枕无忧了。

然而Redis的持久化机制,全量持久化则往往需要额外较大的内存,而在高并发场景下,内存本来就很紧张,如果造成swap,就会影响性能。增量持久化也涉及到写磁盘和fsync,也是会拖慢处理的速度,在平时还好,如果高并发场景下,仍然会影响吞吐量。

所以在架构设计角度,缓存就是缓存,要意识到数据会随时丢失的,要意识到缓存的存着的目的是拦截到数据库的请求。如果为了保证缓存的数据不丢失,从而影响了缓存的吞吐量,甚至稳定性,让缓存响应不过来,甚至挂掉,所有的请求击穿到数据库,就是更加严重的事情了。

如果非常需要进行持久化,可以考虑使用levelDB此类的,对于随机写入性能较好的key-value持久化存储,这样只有部分的确需要持久化的数据,才进行持久化,而非无论什么数据,通通往Redis里面扔,同时统一开启了持久化。

三、基于缓存的架构设计要点

所以基于缓存的设计:

1、多层次

这样某一层的缓存挂了,还有另一层可以撑着,等待缓存的修复,例如分布式缓存因为某种原因挂了,因为持久化的原因,同步机制的原因,内存过大的原因等,修复需要一段时间,在这段时间内,至少本地缓存可以抗一阵,不至于一下子就击穿数据库。而且对于特别特别热的数据,热到导致集中式的缓存处理不过来,网卡也被打满的情况,由于本地缓存不需要远程调用,也是分布在应用层的,可以缓解这种问题。

2、分场景

到底要解决什么问题,可以选择不同的缓存。是要存储大的无格式的数据,还是要存储小的有格式的数据,还是要存储一定需要持久化的数据。具体的场景下一节详细谈。

3、要分片

使得每一个缓存实例都不大,但是实例数目比较多,这样一方面可以实现负载均衡,防止单个实例称为瓶颈或者热点,另一方面如果一个实例挂了,影响面会小很多,高可用性大大增强。分片的机制可以在客户端实现,可以使用中间件实现,也可以使用Redis的Cluster的方式,分片的算法往往都是哈希取模,或者一致性哈希。

四、缓存的使用场景

当你的应用扛不住,知道要使用缓存了,应该怎么做呢?

场景1:和数据库中的数据结构保持一致,原样缓存

这种场景是最常见的场景,也是很多架构使用缓存的适合,最先涉及到的场景。

基本就是数据库里面啥样,我缓存也啥样,数据库里面有商品信息,缓存里面也放商品信息,唯一不同的是,数据库里面是全量的商品信息,缓存里面是最热的商品信息。

每当应用要查询商品信息的时候,先查缓存,缓存没有就查数据库,查出来的结果放入缓存,从而下次就查到了。

这个是缓存最最经典的更新流程。这种方式简单,直观,很多缓存的库都默认支持这种方式。

场景2:列表排序分页场景的缓存

有时候我们需要获得一些列表数据,并对这些数据进行排序和分页。

例如我们想获取点赞最多的评论,或者最新的评论,然后列出来,一页一页的翻下去。

在这种情况下,缓存里面的数据结构和数据库里面完全不一样。

如果完全使用数据库进行实现,则按照某种条件将所有的行查询出来,然后按照某个字段进行排序,然后进行分页,一页一页的展示。

但是当数据量比较大的时候,这种方式往往成为瓶颈,首先涉及的数据库行数比较多,而且排序也是个很慢的活,尽管可能有索引,分页也是翻页到最后,越是慢。

在缓存里面,就没必要每行一个key了,而是可以使用Redis的列表方式进行存储,当然列表的长短是有限制的,肯定放不下数据库里面这么多,但是大家会发现其实对于所有的列表,用户往往没有耐心看个十页八页的,例如百度上搜个东西,也是有排序和分页的,但是你每次都往后翻了吗,每页就十条,就算是十页,或者一百页,也就一千条数据,如果保持ID的话,完全放的下。

如果已经排好序,放在Redis里面,那取出列表,翻页就非常快了。

可以后台有一个线程,异步的初始化和刷新缓存,在缓存里面保存一个时间戳,当有更新的时候,刷新时间戳,异步任务发现时间戳改变了,就刷新缓存。

场景3:计数缓存

计数对于数据库来讲,是一个非常繁重的工作,需要查询大量的行,最后得出计数的结论,当数据改变的时候,需要重新刷一遍,非常影响性能。

因此可以有一个计数服务,后端是一个缓存,将计数作为结果放在缓存里面,当数据有改变的时候,调用计数服务增加或者减少计数,而非通过异步数据库count来更新缓存。

计数服务可以使用Redis进行单个计数,或者hash表进行批量计数

场景4:重构维度缓存

有时候数据库里面保持的数据的维度是为了写入方便,而非为了查询方便的,然而同时查询过程,也需要处理高并发,因而需要为了查询方便,将数据重新以另一个维度存储一遍,或者说将多给数据库的内容聚合一下,再存储一遍,从而不用每次查询的时候都重新聚合,如果还是放在数据库,比较难维护,放在缓存就好一些。

例如一个商品的所有的帖子和帖子的用户,以及一个用户发表过的所有的帖子就是属于两个维度。

这需要写入一个维度的时候,同时异步通知,更新缓存中的另一个维度。

在这种场景下,数据量相对比较大,因而单纯用内存缓存memcached或者redis难以支撑,往往会选择使用levelDB进行存储,如果levelDB的性能跟不上,可以考虑在levelDB之前,再来一层memcached。

场景5:较大的详情内容数据缓存

对于评论的详情,或者帖子的详细内容,属于非结构化的,而且内容比较大,因而使用memcached比较好。

五、缓存三大矛盾问题

1、缓存实时性和一致性问题:当有了写入后咋办?

虽然使用了缓存,大家心里都有一个预期,就是实时性和一致性得不到完全的保证,毕竟数据保存了多份,数据库一份,缓存中一份,当数据库中因写入而产生了新的数据,往往缓存是不会和数据库操作放在一个事务里面的,如何将新的数据更新到缓存里面,什么时候更新到缓存里面,不同的策略不一样。

从用户体验角度,当然是越实时越好,用户体验越流畅,完全从这个角度出发,就应该有了写入,马上废弃缓存,触发一次数据库的读取,从而更新缓存。但是这和第三个问题,高并发就矛盾了,如果所有的都实时从数据库里面读取,高并发场景下,数据库往往受不了。

2、缓存的穿透问题:当没有读到咋办?

为什么会出现缓存读取不到的情况呢?

第一:可能读取的是冷数据,原来从来没有访问过,所以需要到数据库里面查询一下,然后放入缓存,再返回给客户。

第二:可能数据因为有了写入,被实时的从缓存中删除了,就如第一个问题中描述的那样,为了保证实时性,当数据库中的数据更新了之后,马上删除缓存中的数据,导致这个时候的读取读不到,需要到数据库里面查询后,放入缓存,再返回给客户。

第三:可能是缓存实效了,每个缓存数据都会有实效时间,过了一段时间没有被访问,就会失效,这个时候数据就访问不到了,需要访问数据库后,再放入缓存。

第四:数据被换出,由于缓存内存是有限的,当使用快满了的时候,就会使用类似LRU策略,将不经常使用的数据换出,所以也要访问数据库。

第五:后端确实也没有,应用访问缓存没有,于是查询数据库,结果数据库里面也没有,只好返回客户为空,但是尴尬的是,每次出现这种情况的时候,都会面临着一次数据库的访问,纯属浪费资源,常用的方法是,讲这个key对应的结果为空的事实也进行缓存,这样缓存可以命中,但是命中后告诉客户端没有,减少了数据库的压力。

无论哪种原因导致的读取缓存读不到的情况,该怎么办?是个策略问题。

一种是同步访问数据库后,放入缓存,再返回给客户,这样实时性最好,但是给数据库的压力也最大。

另一种方式就是异步的访问数据库,暂且返回客户一个fallback值,然后同时触发一个异步更新,这样下次就有了,这样数据库压力小很多,但是用户就访问不到实时的数据了。

3、缓存对数据库高并发访问:都来访问数据库咋办?

我们本来使用缓存,是来拦截直接访问数据库请求的,从而保证数据库大本营永远处于健康的状态。但是如果一遇到不命中,就访问数据库的话,平时没有什么问题,但是大促情况下,数据库是受不了的。

一种情况是多个客户端,并发状态下,都不命中了,于是并发的都来访问数据库,其实只需要访问一次就好,这种情况可以通过加锁,只有一个到后端来实现。

另外就是即便采取了上述的策略,依然并发量非常大,后端的数据库依然受不了,则需要通过降低实时性,将缓存拦在数据库前面,暂且撑住,来解决。

六、解决缓存三大矛盾的刷新策略

1、实时策略

所谓的实时策略,是平时缓存使用的最常用的策略,也是保持实时性最好的策略。

读取的过程,应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。如果命中,应用程序从cache中取数据,取到后返回。

写入的过程,把数据存到数据库中,成功后,再让缓存失效,失效后下次读取的时候,会被写入缓存。那为什么不直接写缓存呢?因为如果两个线程同时更新数据库,一个将数据库改为10,一个将数据库改为20,数据库有自己的事务机制,可以保证如果20是后提交的,数据库里面改为20,但是回过头来写入缓存的时候就没有事务了,如果改为20的线程先更新缓存,改为10的线程后更新缓存,于是就会长时间出现缓存中是10,但是数据库中是20的现象。

这种方式实时性好,用户体验好,是默认应该使用的策略。

2、异步策略

所谓异步策略,就是当读取的时候读不到的时候,不直接访问数据库,而是返回一个fallback数据,然后往消息队列里面放入一个数据加载的事件,在背后有一个任务,收到事件后,会异步的读取数据库,由于有队列的作用,可以实现消峰,缓冲对数据库的访问,甚至可以将多个队列中的任务合并请求,合并更新缓存,提高了效率。

当更新的时候,异步策略总是先更新数据库和缓存中的一个,然后异步的更新另一个。

一是先更新数据库,然后异步更新缓存。当数据库更新后,同样生成一个异步消息,放入消息队列中,等待背后的任务通过消息进行缓存更新,同样可以实现消峰和任务合并。缺点就是实时性比较差,估计要过一段时间才能看到更新,好处是数据持久性可以得到保证。

一是先更新缓存,然后异步更新数据库。这种方式读取和写入都用缓存,将缓存完全挡在了数据库的前面,把缓存当成了数据库在用。所以一般会使用有持久化机制和主备的redis,但是仍然不能保证缓存不丢数据,所以这种情况适用于并发量大,但是数据没有那么关键的情况,好处是实时性好。

在实时策略扛不住大促的时候,可以根据场景,切换到上面的两种模式的一个,算是降级策略。

3、定时策略

如果并发量实在太大,数据量也大的情况,异步都难以满足,可以降级为定时刷新的策略,这种情况下,应用只访问缓存,不访问数据库,更新频率也不高,而且用户要求也不高,例如详情,评论等。

这种情况下,由于数据量比较大,建议将一整块数据拆分成几部分进行缓存,而且区分更新频繁的和不频繁的,这样不用每次更新的时候,所有的都更新,只更新一部分。并且缓存的时候,可以进行数据的预整合,因为实时性不高,读取预整合的数据更快。

有关缓存就说到这里,下一节讲分布式事务。

from:https://mp.weixin.qq.com/s/-9wHpKGf7aJSbtShpCcoVg

每个程序员都应该了解的内存知识-0

这个系列文章源于 What Every Programmer Should Know About Memory ,粗读下来觉得很不错,最好能留存下来。同时发现这个系列的文章已经有一部分被人翻译了。故在此转发留存一份,毕竟存在自己收留的才是最可靠的,经常发现很多不错的文章链接失效的情况。

本文转载自,翻译自。本人进行了轻微的修改,感觉更符合原义。

1 简介

早期计算机比现在更为简单。系统的各种组件例如CPU,内存,大容量存储器和网口,由于被共同开发因而有非常均衡的表现。例如,内存和网口并不比CPU在提供数据的时候更(特别的)快。

曾今计算机稳定的基本结构悄然改变,硬件开发人员开始致力于优化单个子系统。于是电脑一些组件的性能大大的落后因而成为了瓶颈。由于开销的原因,大容量存储器和内存子系统相对于其他组件来说改善得更为缓慢。

大容量存储的性能问题往往靠软件来改善: 操作系统将常用(且最有可能被用)的数据放在主存中,因为后者的速度要快上几个数量级。或者将缓存加入存储设备中,这样就可以在不修改操作系统的前提下提升性能。(然而,为了在使用缓存时保证数据的完整性,仍然要作出一些修改)。这些内容不在本文的谈论范围之内,就不作赘述了。

而解决内存的瓶颈更为困难,它与大容量存储不同,几乎每种方案都需要对硬件作出修改。目前,这些变更主要有以下这些方式:

  • RAM的硬件设计(速度与并发度)
  • 内存控制器的设计
  • CPU缓存
  • 设备的直接内存访问(DMA)

本文主要关心的是CPU缓存和内存控制器的设计。在讨论这些主题的过程中,我们还会研究DMA。不过,我们首先会从当今商用硬件的设计谈起。这有助于我们理解目前在使用内存子系统时可能遇到的问题和限制。我们还会详细介绍RAM的分类,说明为什么会存在这么多不同类型的内存。

本文不会包括所有内容,也不会包括最终性质的内容。我们的讨论范围仅止于商用硬件,而且只限于其中的一小部分。另外,本文中的许多论题,我们只会点到为止,以达到本文目标为标准。对于这些论题,大家可以阅读其它文档,获得更详细的说明。

当本文提到操作系统特定的细节和解决方案时,针对的都是Linux。无论何时都不会包含别的操作系统的任何信息,作者无意讨论其他操作系统的情况。如果读者认为他/她不得不使用别的操作系统,那么必须去要求供应商提供其操作系统类似于本文的文档。

在开始之前最后的一点说明,本文包含大量出现的术语“通常”和别的类似的限定词。这里讨论的技术在现实中存在于很多不同的实现,所以本文只阐述使用得最广泛最主流的版本。在阐述中很少有地方能用到绝对的限定词。

1.1 文档结构

这个文档主要视为软件开发者而写的。本文不会涉及太多硬件细节,所以喜欢硬件的读者也许不会觉得有用。但是在我们讨论一些有用的细节之前,我们先要描述足够多的背景。

在这个基础上,本文的第二部分将描述RAM(随机寄存器)。懂得这个部分的内容很好,但是此部分的内容并不是懂得其后内容必须部分。我们会在之后引用不少之前的部分,所以心急的读者可以跳过任何章节来读他们认为有用的部分。

第三部分会谈到不少关于CPU缓存行为模式的内容。我们会列出一些图标,这样你们不至于觉得太枯燥。第三部分对于理解整个文章非常重要。第四部分将简短的描述虚拟内存是怎么被实现的。这也是你们需要理解全文其他部分的背景知识之一。

第五部分会提到许多关于Non Uniform Memory Access (NUMA)系统。

第六部分是本文的中心部分。在这个部分里面,我们将回顾其他许多部分中的信息,并且我们将给阅读本文的程序员许多在各种情况下的编程建议。如果你真的很心急,那么你可以直接阅读第六部分,并且我们建议你在必要的时候回到之前的章节回顾一下必要的背景知识。

本文的第七部分将介绍一些能够帮助程序员更好的完成任务的工具。即便在彻底理解了某一项技术的情况下,距离彻底理解在非测试环境下的程序还是很遥远的。我们需要借助一些工具。

第八部分,我们将展望一些在未来我们可能认为好用的科技。

1.2 反馈问题

作者会不定期更新本文档。这些更新既包括伴随技术进步而来的更新也包含更改错误。非常欢迎有志于反馈问题的读者发送电子邮件。

1.3 致谢

我首先需要感谢Johnray Fuller尤其是Jonathan Corbet,感谢他们将作者的英语转化成为更为规范的形式。Markus Armbruster提供大量本文中对于问题和缩写有价值的建议。

1.4 关于本文

本文题目对David Goldberg的经典文献《What Every Computer Scientist Should Know About Floating-Point Arithmetic》[goldberg]表示致敬。Goldberg的论文虽然不普及,但是对于任何有志于严格编程的人都会是一个先决条件

2 商用硬件现状

鉴于目前专业硬件正在逐渐淡出,理解商用硬件的现状变得十分重要。现如今,人们更多的采用水平扩展,也就是说,用大量小型、互联的商用计算机代替巨大、超快(但超贵)的系统。原因在于,快速而廉价的网络硬件已经崛起。那些大型的专用系统仍然有一席之地,但已被商用硬件后来居上。2007年,Red Hat认为,未来构成数据中心的“积木”将会是拥有最多4个插槽的计算机,每个插槽插入一个四核CPU,这些CPU都是超线程的。(超线程使单个处理器核心能同时处理两个以上的任务,只需加入一点点额外硬件)。也就是说,这些数据中心中的标准系统拥有最多64个虚拟处理器(至今来看2018那年,96核/128核的服务已经是很常见的服务器配置了)。当然可以支持更大的系统,但人们认为4插槽、4核CPU是最佳配置,绝大多数的优化都针对这样的配置。

在不同商用计算机之间,也存在着巨大的差异。不过,我们关注在主要的差异上,可以涵盖到超过90%以上的硬件。需要注意的是,这些技术上的细节往往日新月异,变化极快,因此大家在阅读的时候也需要注意本文的写作时间。

这么多年来,个人计算机和小型服务器被标准化到了一个芯片组上,它由两部分组成: 北桥和南桥,见图2.1。

图2.1 北桥和南桥组成的结构

CPU通过一条通用总线(前端总线,FSB)连接到北桥。北桥主要包括内存控制器和其它一些组件,内存控制器决定了RAM芯片的类型。不同的类型,包括DRAM、Rambus和SDRAM等等,要求不同的内存控制器。

为了连通其它系统设备,北桥需要与南桥通信。南桥又叫I/O桥,通过多条不同总线与设备们通信。目前,比较重要的总线有PCI、PCI Express、SATA和USB总线,除此以外,南桥还支持PATA、IEEE 1394、串行口和并行口等。比较老的系统上有连接北桥的AGP槽。那是由于南北桥间缺乏高速连接而采取的措施。现在的PCI-E都是直接连到南桥的。

这种结构有一些需要注意的地方:

  • 从某个CPU到另一个CPU的数据需要走它与北桥通信的同一条总线。
  • 与RAM的通信需要经过北桥
  • RAM只有一个端口。(本文不会介绍多端口RAM,因为商用硬件不采用这种内存,至少程序员无法访问到。这种内存一般在路由器等专用硬件中采用。)
  • CPU与南桥设备间的通信需要经过北桥

在上面这种设计中,瓶颈马上出现了。第一个瓶颈与设备对RAM的访问有关。早期,所有设备之间的通信都需要经过CPU,结果严重影响了整个系统的性能。为了解决这个问题,有些设备加入了直接内存访问(DMA)的能力。DMA允许设备在北桥的帮助下,无需CPU的干涉,直接读写RAM。到了今天,所有高性能的设备都可以使用DMA。虽然DMA大大降低了CPU的负担,却占用了北桥的带宽,与CPU形成了争用。

第二个瓶颈来自北桥与RAM间的总线。总线的具体情况与内存的类型有关。在早期的系统上,只有一条总线,因此不能实现并行访问。近期的RAM需要两条独立总线(或者说通道,DDR2就是这么叫的,见图2.8),可以实现带宽加倍。北桥将内存访问交错地分配到两个通道上。更新的内存技术(如FB-DRAM)甚至加入了更多的通道。

由于带宽有限,我们需要以一种使延迟最小化的方式来对内存访问进行调度。我们将会看到,处理器的速度比内存要快得多,需要等待内存。如果有多个超线程核心或CPU同时访问内存,等待时间则会更长。对于DMA也是同样。

除了并发以外,访问模式也会极大地影响内存子系统、特别是多通道内存子系统的性能。关于访问模式,可参见2.2节。

在一些比较昂贵的系统上,北桥自己不含内存控制器,而是连接到外部的多个内存控制器上(在下例中,共有4个)。

图2.2 拥有外部控制器的北桥

这种架构的好处在于,多条内存总线的存在,使得总带宽也随之增加了。而且也可以支持更多的内存。通过同时访问不同内存区,还可以降低延时。对于像图2.2中这种多处理器直连北桥的设计来说,尤其有效。而这种架构的局限在于北桥的内部带宽,非常巨大(来自Intel)。(出于完整性的考虑,还需要补充一下,这样的内存控制器布局还可以用于其它用途,比如说「内存RAID」,它可以与热插拔技术一起使用。)

使用外部内存控制器并不是唯一的办法,另一个最近比较流行的方法是将控制器集成到CPU内部,将内存直连到每个CPU。这种架构的走红归功于基于AMD Opteron处理器的SMP系统。图2.3展示了这种架构。Intel则会从Nehalem处理器开始支持通用系统接口(CSI),基本上也是类似的思路——集成内存控制器,为每个处理器提供本地内存。

图2.3 集成的内存控制器

通过采用这样的架构,系统里有几个处理器,就可以有几个内存库(memory bank)。比如,在4 CPU的计算机上,不需要一个拥有巨大带宽的复杂北桥,就可以实现4倍的内存带宽。另外,将内存控制器集成到CPU内部还有其它一些优点,这里就不赘述了。

同样也有缺点。首先,系统仍然要让所有内存能被所有处理器所访问,导致内存不再是统一的资源(NUMA即得名于此)。处理器能以正常的速度访问本地内存(连接到该处理器的内存)。但它访问其它处理器的内存时,却需要使用处理器之间的互联通道。比如说,CPU 1 如果要访问CPU 2 的内存,则需要使用它们之间的互联通道。如果它需要访问CPU 4 的内存,那么需要跨越两条互联通道。

使用互联通道是有代价的。在讨论访问远端内存的代价时,我们用「NUMA因子」这个词。在图2.3中,每个CPU有两个层级: 相邻的CPU,以及两个互联通道外的CPU。在更加复杂的系统中,层级也更多。甚至有些机器有不止一种连接,比如说IBM的x445和SGI的Altix系列。CPU被归入节点,节点内的内存访问时间是一致的,或者只有很小的NUMA因子。而在节点之间的连接代价很大,而且有巨大的NUMA因子。

目前,已经有商用的NUMA计算机,而且它们在未来应该会扮演更加重要的角色。人们预计,从2008年底开始,每台SMP机器都会使用NUMA。每个在NUMA上运行的程序都应该认识到NUMA的代价。在第5节中,我们将讨论更多的架构,以及Linux内核为这些程序提供的一些技术。

除了本节中所介绍的技术之外,还有其它一些影响RAM性能的因素。它们无法被软件所左右,所以没有放在这里。如果大家有兴趣,可以在第2.1节中看一下。介绍这些技术,仅仅是因为它们能让我们绘制的RAM技术全图更为完整,或者是可能在大家购买计算机时能够提供一些帮助。

以下的两节主要介绍一些入门级的硬件知识,同时讨论内存控制器与DRAM芯片间的访问协议。这些知识解释了内存访问的原理,程序员可能会得到一些启发。不过,这部分并不是必读的,心急的读者可以直接跳到第2.2.5节。

2.1 RAM类型

这些年来,出现了许多不同类型的RAM,各有差异,有些甚至有非常巨大的不同。那些很古老的类型已经乏人问津,我们就不仔细研究了。我们主要专注于几类现代RAM,剖开它们的表面,研究一下内核和应用开发人员们可以看到的一些细节。

第一个有趣的细节是,为什么在同一台机器中有不同的RAM?或者说得更详细一点,为什么既有静态RAM(SRAM {SRAM还可以表示「同步内存」。}),又有动态RAM(DRAM)。功能相同,前者更快。那么,为什么不全部使用SRAM?答案是,代价。无论在生产还是在使用上,SRAM都比DRAM要贵得多。生产和使用,这两个代价因子都很重要,后者则是越来越重要。为了理解这一点,我们分别看一下SRAM和DRAM一个位的存储的实现过程。

在本节的余下部分,我们将讨论RAM实现的底层细节。我们将尽量控制细节的层面,比如,在「逻辑的层面」讨论信号,而不是硬件设计师那种层面,因为那毫无必要。

2.1.1 静态RAM

图2.4 6-T静态RAM

图2.4展示了6晶体管SRAM的一个单元。核心是4个晶体管M 1 – M 4 ,它们组成两个交叉耦合的反相器。它们有两个稳定的状态,分别代表0和1。只要保持V dd 有电,状态就是稳定的。

当访问单元的状态时,需要拉升WL的电平。使得

和 上可以读取状态。如果需要覆盖单元状态,先将 和 设置为期望的值,然后升起WL电平。由于外部的驱动强于内部的4个晶体管(M 1 – M 4

),所以旧状态会被覆盖。

更多详情,可以参考[sramwiki]。为了下文的讨论,需要注意以下问题:

  • 一个单元需要6个晶体管。也有采用4个晶体管的SRAM,但有缺陷。
  • 维持状态需要恒定的电源。
  • 升起WL后立即可以读取状态。信号与其它晶体管控制的信号一样,是直角的(快速在两个状态间变化)。
  • 状态稳定,不需要刷新循环。

SRAM也有其它形式,不那么费电,但比较慢。由于我们需要的是快速RAM,因此不在关注范围内。这些较慢的SRAM的主要优点在于接口简单,比动态RAM更容易使用。

2.1.2 动态RAM

动态RAM比静态RAM要简单得多。图2.5展示了一种普通DRAM的结构。它只含有一个晶体管和一个电容器。显然,这种复杂性上的巨大差异意味着功能上的迥异。

图2.5 1-T动态RAM

动态RAM的状态是保持在电容器C中。晶体管M用来控制访问。如果要读取状态,拉升访问线AL,这时,可能会有电流流到数据线DL上,也可能没有,取决于电容器是否有电。如果要写入状态,先设置DL,然后升起AL一段时间,直到电容器充电或放电完毕。

动态RAM的设计有几个复杂的地方。由于读取状态时需要对电容器放电,所以这一过程不能无限重复,不得不在某个点上对它重新充电。

更糟糕的是,为了容纳大量单元(现在一般在单个芯片上容纳10的9次方以上的RAM单元),电容器的容量必须很小(0.000000000000001法拉以下)。这样,完整充电后大约持有几万个电子。即使电容器的电阻很大(若干兆欧姆),仍然只需很短的时间就会耗光电荷,称为「泄漏」。

这种泄露就是现在的大部分DRAM芯片每隔64ms就必须进行一次刷新的原因。在刷新期间,对于该芯片的访问是不可能的,这甚至会造成半数任务的延宕。(相关内容请察看【highperfdram】一章)

这个问题的另一个后果就是无法直接读取芯片单元中的信息,而必须通过信号放大器将0和1两种信号间的电势差增大。

最后一个问题在于电容器的冲放电是需要时间的,这就导致了信号放大器读取的信号并不是典型的矩形信号。所以当放大器输出信号的时候就需要一个小小的延宕,相关公式如下

这就意味着需要一些时间(时间长短取决于电容C和电阻R)来对电容进行冲放电。另一个负面作用是,信号放大器的输出电流不能立即就作为信号载体使用。图2.6显示了冲放电的曲线,x轴表示的是单位时间下的R*C。

与静态RAM可以即刻读取数据不同的是,当要读取动态RAM的时候,必须花一点时间来等待电容的冲放电完全。这一点点的时间最终限制了DRAM的速度。

当然了,这种读取方式也是有好处的。最大的好处在于缩小了规模。一个动态RAM的尺寸是小于静态RAM的。这种规模的减小不单单建立在动态RAM的简单结构之上,也是由于减少了静态RAM的各个单元独立的供电部分。以上也同时导致了动态RAM模具的简单化。

综上所述,由于不可思议的成本差异,除了一些特殊的硬件(包括路由器什么的)之外,我们的硬件大多是使用DRAM的。这一点深深的影响了咱们这些程序员,后文将会对此进行讨论。在此之前,我们还是先了解下DRAM的更多细节。

2.1.3 DRAM 访问

一个程序选择了一个内存位置使用到了一个虚拟地址。处理器转换这个到物理地址最后将内存控制选择RAM芯片匹配了那个地址。在RAM芯片去选择单个内存单元,部分的物理地址以许多地址行的形式被传递。

它单独地去处理来自于内存控制器的内存位置将完全不切实际:4G的RAM将需要 $ 2^32 $ 地址行。地址传递DRAM芯片的这种方式首先必须被路由器解析。一个路由器的N多地址行将有$ 2^N $输出行。这些输出行能被使用到选择内存单元。使用这个直接方法对于小容量芯片不再是个大问题。

from:https://www.tuicool.com/articles/IfueY3A

HTTP协议

我们知道目前很多应用系统中的内容传输协议采用的HTTP协议,因此不管你是前端人员、后端人员、运维人员,甚至是管理人员,都需要掌握HTTP知识!!

HTTP发展历史

HTTP/0.9  

该版本只有一个命令GET;没有HEADER等描述数据的信息; 服务器发送完毕,就关闭TCP连接。

HTTP/1.0  

该版本增加了很多命令;增加status code 和header;多字符集支持、多部分发送、权限、缓存等。

HTTP/1.1   

该版本增加了持久连接Pipeline,增加host和其他一些命令。持久连接会在HTTP特性中介绍;如果没有pipeline,那么Web服务器就需要串行处理请求,而有了pipeline,Web服务器就并行处理请求;而增加host实现了一台物理设备可以运行多个web服务。

HTTP/2.0   

所有数据以二进制传输,之前版本使用字符串进行传输;同一个连接 里面发送多个请求不再需要按照顺序来;头信息压缩以及推送等提高效率的功能。

HTTP三次握手

为什么要三次握手?因为网络是有可能延迟的,当客户端没有收到服务端的确认包,如果没有第三次握手,那么服务端不知道上次传输是不是被客户端正常接收了,如果没有接收,服务端的这个端口也是打开的,这就比较浪费资源。

HTTP报文

HTTP报文分为请求报文响应报文,请求报文和响应报文分为起始行、首部(header)和主体(body),请求报文的首部包括三部分,分别是HTTP方法、资源目录和协议,而响应报文的首部包括协议版本、状态码和状态吗对应的意思,比如200状态的意思是ok。需要注意的是:HTTP header和HTTP body之间以一行分隔。

HTTP方法  

HTTP方法定义对资源的操作,常用的有GET、POST等,这就就不详细展开了。

HTTP Code  

HTTP Code用于定义服务器对请求的处理结果,各个区间的code有不用的语义。1xx  表示信息响应类,表示接收到请求并且继续处理;2xx 表示成功;3xx 表示重定向;4xx 表示客户端出错;5xx 表示服务器出错。

HTTP特性

跨域请求   

同源策略,也就是说当两个请求的URL的协议、host和端口都相同的情况下,我们才认为这两个请求是同域的即同源,而只要协议、host和端口只要有一项是不同的,我们就认为是不同源的,即跨域,例如:

http://www.mukedada.com:80

http://www.mukedada.com:8080

上述两个请求就是跨域请求。需要注意的是跨域请求不是说浏览器限制了发起跨站请求,浏览器只是将返回结果拦截下来,最好的例子就是CSRF跨站脚本攻击。如果我们想让浏览器放行返回结果,则通过以下方法:

  1. 服务端设置Access-Control-Allow-Origin参数为允许,例如’Access-Control-Allow-Origin’ : ‘*’
  2. <link>、<img>和<script>三标签中的请求是允许跨域的,这也是JSONP的跨域做法。
Cache  Control 

对于静态资源,比如说image、js等,它们是不会经常方式变更的,而且它们的容量比较大,如果我们每次访问都要从服务器从获取相应数据,那么性能就会变得比较差,因此HTTP协议定义一些和缓存相关的参数。

可缓存性,表示在哪些地方可以缓存,比如说客户端浏览器、代理服务器等,它有三个常用的参数:public、private、no-cache。public 表明响应可以被任何对象缓存,包括发送请求的客户端浏览器、代理服务器等等;private 表示响应只能被单个用户缓存,不能作为共享缓存,即代理服务器不能缓存它;no-cache表明强制所有缓存了该响应的缓存用户,在使用已存储的缓存之前,发送带验证器的请求到源始服务器。

到期,max-age=<seconds>,设置缓存存储的最大周期,超过这个时间缓存就被认为过期。s-maxage=<seconds> 它的作用域仅在共享缓存(比如各个代理)。max-stale=<seconds> 表明客户端愿意接收一个已过期的资源。

验证,must-revalidate,缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源。proxy-revalidate,与must-revalidate作用相同,但它仅适用于共享缓存(例如代理),并被私有缓存忽略。

其他。no-store,客户端和代理服务器不存储任何缓存,而是直接从服务器获取内容。no-transform:不得对资源进行转换或转变。Content-Encoding, Content-Range, Content-Type等HTTP头不能由代理修改。例如,非透明代理可以对图像格式进行转换,以便节省缓存空间或者减少缓慢链路上的流量。 no-transform指令不允许这样做。

Cookie   

服务端通过Set-Cookie将相关数据保存到浏览器中,而这些相关数据就是Cookie,那么,下次在同域的请求中就会带上这些Cookie,Cookie是键值对,可以设置多个。Cookie中通过max-age和expires设置过期时间,Secure值在https的时候发送,HttpOnly无法通过document.cookie访问。具体可以参考Session 和 Cookie

资源验证  

在Cache Control中我们介绍当设置no-cache参数时,表明每次请求都要到服务器验证,验证结果表明可以读取本地缓存才可以从本地读取缓存。只有到数据发生修改时,我们才需要从服务端读取最新数据,否则从本地读取缓存。此时,判断数据是否发生修改就变得尤为重要,通常我们采用Last-Modfied和Etag两个验证头来验证数据是否发生修改。其中Last-Modifed 通常配合If-Modified-Since或者If-UnModified-Since使用,而Etag 通常配合If-Match或者If-Non-Match使用。为了帮助大家理解,我举一个栗子。假设我们访问mudedada.com返回头信息包含:

Last-Modified:888

Etag:123

下一次访问mukedada.com的请求头中就会包含:

If-Modified-Since:888

If-Non-Match:123

服务器会比较请求头中的Last-Modified、Etag 和服务器中的对应值是否相同,如果不相同则重新获取,否则从本地缓存中获取。

长连接   

我们知道一个HTTP需要创建一个TCP连接,完成之后就关闭TCP连接,这个成本比较高(因为创建一个TCP连接需要通过三次握手),所以在HTTP/1.1开始支持长连接,请求头标识是Connection:keep-alive。如下图所示,同一个Connection ID表示同一个连接。需要注意的是同一个连接只能是同域请求。

数据协商   

数据协商指的是客户端向服务端发送请求时,客户端会声明它希望服务端返回个格式是什么?服务端根据客户端的声明来判断返回什么要的数据。其中客户端通过Accept、Accept-Encoding等参数进行设置,而服务端通过Content-Type等参数进行设置。

客户端相关参数

  1. Accept指定返回数据类型;
  2. Accept-Encoding指定服务端的数据压缩方式,目前服务端的压缩算法有gzip, deflate, br等;
  3. Accept-Language指定返回数据的语言,例如 Accept-Language:  zh-CN,zh;q=0.9,en;q=0.8,其中q表示的是权重,也就是说浏览器更希望服务器返回的是中文;
  4. User-Agent表示浏览器的相关信息,它能区分是移动端浏览器还是PC端浏览器,从而返回特定的页面。

服务端相关参数:

  1. Content-Type指的是服务端返回的数据类型;
  2. Content-Encoding对应客户端的Accept-Encoding,指的是数据压缩方式;
  3. Content-Language服务端语言。

from:https://mp.weixin.qq.com/s/vRQ2zuKxyLaBxcm9lolL7w