进程内缓存技术,究竟怎么玩

自从美国总统特朗普3月23日在白宫正式签署对华贸易备忘录,酝酿已久的中美贸易大战算是正式打响了。毫无疑问,从行业和企业的角度来看,这一波互联网浪潮中兴起的出口电商肯定是最受伤的那个,如果贸易战刹不住车,将影响全球开放贸易格局,出口电商在诸多掣肘中将变得举步维艰。而就算没有中美贸易战,出口电商行业内的波云诡谲也不曾明朗过。2017年底,知名出口电商Wish中国总裁丁浩川离职,距离上任刚刚超过1年而已。到今年2月,包括丁浩川、中国区总监方芳等四位高管均已先后离职。伴随离职潮的是卖家们反馈的订单断崖式下跌。另一边,被联络互动收购的电商品牌新蛋(Newegg)却动作频频,3月27日,其所主办的&Newegg新蛋全球卖家峰会暨ttchic品牌发布会&在杭州举行,加入联络互动后,新蛋对把中国货卖到世界这件事已经摩拳擦掌。而在这之前,新蛋作为发家于美国而后成为中国公司的品牌,在进口电商这件事上相对于那些还要去外边寻觅产品的本土电商而言,本身就具备了充分的渠道及平台优势,在这种情况下大举进攻出口电商明显是冲着它的前景去的。可以说,中美贸易战只是把默默无闻的出口电商推向了风口,让玩家们的行为开始明面化,而从玩法上来看,硝烟之中,出口电商除了革除自身顽疾,固有玩法可能也要发生转变。出口电商应该是跨境电商的主战场跨境电商无论如何都带有&入境&、&出境&两层含义,但不知何故互联网行业一谈论起跨境电商,首先想到的都是海淘、考拉海购之类的进口电商,在把国货往外卖这件事上鲜有人关注。1、出口电商市场既有大份额也有广前景根据中国电子商务研究中心出具的《2017年(上)中国电子商务市场数据监测报告》,2017上半年中国跨境电商交易规模3.6万亿元,同比增长30.7%,其中,出口跨境电商交易规模达2.75万亿元(占比81.5%),而进口跨境电商交易规模仅为8624亿元(占比18.5%)。此外,Newegg新蛋副总裁Sophia表示,2018年出口跨境规模将达到6.8万亿。虽然不是舆论焦点,但据统计,在国内147家电商平台中,有46%的平台已经开展了海外业务。其中,天猫和京东两家电商巨头已经通过资本收购,抢占了大部分东南亚市场,并且仍将高速扩张。而从市场上来看,我们沉醉于双11、618等辉煌数据中不可自拔,但国外的电商市场同样火热,典型的例如美国,3.15亿居民、2.55亿网民、1.84亿在线购买者,电子商务交易额约占全球电子商务交易额的25%,有很大的市场空间可供发挥。2、中国制造的形象早已不再一样在不少人心中,国货的低端形象或许是出口电商面临的最大问题。但是,出口电商之所以能够迎来快速增长,与中国制造形象的改变也有很大关系。无人机大疆在海外大显身手;电子配件ANKER(跨境电商神话品牌)、Aukey(傲基国际品牌)、Bludio(中高端耳机)等在亚马逊、eBay平台电子配件TOP榜上有名;MOPS(联络互动旗下智能生活品牌)产品在新蛋上大放异彩;快时尚品牌ShenIn、Choies择尚(新三板已上市了)在服饰和史上方面也为我们国人扬眉吐气。在3月27日新蛋的招商会上,一定程度上能够代表&精品国货&的小米、海康威视、联想、科大讯飞、宏图三胞皆现身,户外、服装(时尚)、家居、汽配、工具等多个行业较为优质的企业都有借新蛋出海的意愿。至少在电商层面,国货已经有充分的信心去面对世界客户。3、政策驱动始终是根本保障除了一带一路、产业结构转型等大局需要,出口电商还肩负平衡国际贸易、调节外汇等诸多责任,也因此,不只是企业层面,国家层面对出口电商的支持也不遗余力。表:中国出口跨境电商政策(来源:电子商务研究中心)一方面,政策支持下杭州、深圳等城市出现了集中的出口电商聚合区域;另一方面,一个行业的发展没有大环境支持显然是不能长久的,不同于本土电商或进口电商对线下实体经济可能造成冲击,出口电商在任何层面都有更充足的发展底气。鱼龙混杂,出口电商苦衷不少但是,即便出口电商在市场规模、前景、产品质量以及政策层面都有充分的发展保障,作为一种走出去面对众多国度和文化的业务形态,出口电商也存在着诸多&苦衷&。1、&全息行业&,廉价低质损害整体形象在进口电商或者本土电商这里,如果出现了假货、劣质货或者品质很差的正品,损害的往往是某个企业、某个品牌或某个渠道的信誉。消费者虽然感觉上当,但下次至多换个地方再次购物。而出口电商则恰恰相反,它带有某种&全息行业&的特征,也即,仍何一个行业的参与者都可能影响整体的市场印象,出口电商之间既是竞争的关系,更共同肩负行业形象的责任,局部即是整体,整体即是局部。&一颗老鼠屎坏一锅粥&倒是其次,重要的是,在这个庞大的市场上,那些有心做好产品、好品牌的出口电商无法控制整个行业,很多时候都是身不由己。两年前,美国9个州发生了10起平衡车起火事件,平衡车被亚马逊下架,最终导致整个平衡车消费市场对来自中国的平衡车整机和零件都产生怀疑,最终波及对中国制造的信任,相信很多不相关的厂商只能一脸问号,却无力控制。2、看似美好的目的地,可能是沼泽出口电商的出口一般有两个地域方向,即所谓&发展中国家&及&发达国家&。前者,入局好处在于市场处于空白状态,市场有着无限的可能,例如天猫和京东选择的东南亚市场,鲜有当地竞争者,无论对于平台还是国货出海都十分有利。但是,东南亚、非洲这些地区同时存在人均购买力低、网购习惯未成熟、物流硬件条件不完善的弊端,无论是主动推动物流体系的建立还是培养市场网购习惯都需要极大的成本投入。后者,虽然基础设施完善,但受全球经济下行的影响,以美国为代表,欧美近年来贸易壁垒开始回潮,如果在之前没有打好深厚的根基,在贸易政策冲击下将举步维艰。按照联络互动董事长何志涛的说法,&目前看下来所有跨境(出口)电商比较难做起来的,都是因为他们在海外没有自己独立的用户(即年付费3次以上、数量可观的用户群体)。&这也是为什么亚马逊可以笑傲欧美市场的直接原因,而世界排名第一、超越亚马逊的阿里却迟迟没有大举进军的动作。3、多对多,&出口&高出&进口&一个数量级进口电商、本土电商还有个特点,不论是什么类型的产品、品牌,最终都归于&中国&市场,在营销策略、产品策略上十分有针对性,是一个&多对一&的市场。而出口电商,往往针对不只一个独立市场,众多品牌、产品出海面对众多不同的市场,形成&多对多&的局面,无论对品牌商还是平台都是不小的挑战。这种&做乘法&的市场,其复杂度高出了一个数量级。尤其是在运营上,一些本来简单的细节变得十分复杂。例如商品信息简介不同地区文化千差万别,宗教忌讳、词汇歧义本身就足够作为课题深度研究了。再例如,发生在wish大门口的卖家横幅申讨事件,就是由于对目的地市场政策翻译失误给卖家带来重大损失所导致。三重运营才能做好出口电商问题并非无解,只是解决方案既需要硬实力,更需要运营的技巧。1、平台运营:硬实力的较量出口电商的发展也有不短的时间了,最终,我们发现唱戏的还是那些大型的互联网企业,在速卖通(背后是)、ebay的狙击下,曾经风光无两、发展超过10年的出口电商第一股面临股价业绩双跌的境况。大张旗鼓搞招商大会的新蛋同样来头不小,2001年成立后到目前销售的商品种类多达17个行业750个品类,市场覆盖5 0个国家,拥有超过3,600万注册会员,本身就已经是北美最大的科技类电商。新蛋深耕英语国家近20年,在电商规模成熟、客户资源优质的北美市场耕耘多时,已经具备了足够深厚的根基,这是它敢于到中国市场抢食出口电商的根本原因。由此,出口电商的平台运营,无论是本土的平台还是国外的平台,说来说去都是硬实力在PK,普通电商可以在阿里、京东主宰的互联网环境中仍然发展出100多家,而出口电商平台的数量两只手就能数过来,更多的都是借平台做生意的普通中小创业者,无法自立门户。2、品牌运营:供应商品牌塑造B端品牌借平台出海,除了卖东西挣钱,也一定带有塑造品牌、开拓市场的目的。何志涛在接受采访时表示,&大部分中国制造只是&中国制造&,没有品牌,在出海过程中利润率也比较低,带来的口碑也不太好。&,&其实中国自己的品牌在全球被大家广泛关注认同的数量是非常有限的。&海康威视、小米、联想、科大讯飞、宏图三胞等之所以与新蛋合作,绝不仅仅是看中其销量,更多的是希望借助新蛋平台的力量打造国际形象。新蛋似乎&心照不宣&,同时邀请了服务商跨境支付的PingPong,跨境物流心怡科技、普路通,ERP系统服务商通途等到场表达自己对品牌们的支持。而联络互动依托于新蛋发展出来的ttchic品牌,其目的也无非是为跨境企业提供品牌、营销、推广、仓储、物流、法务、财务等一站式出海服务,服务重点在于品牌和营销体系的搭建,最终试图为卖家刷新海外形象。事实上,在塑造品牌过程中,国外市场所需要的投入并不比国内多,只是更加需要技巧。品牌商们在国内依靠媒体、微博、微信、主流及垂直电商平台、ASO 应用商店的优化和其他一些付费渠道来塑造形象,而美国等国博主文化强大,博主联盟有着非常分散的渠道,社交媒体渠道也更为丰富。图:国外流量渠道(来源:截取)在ttchic对外宣传的卖点里,就有&帮助卖家,运用Newegg新蛋现有营销体系,最终实现当地主流媒体、社交网络推广及产品销售&,其实就是表达自己对复杂流量渠道的运营更有经验。3、机会运营:贸易战背后有新的产品逻辑贸易战最主要的方式是加税,最直接的结果是外来产品价格上涨,保护本国产品的市场。这种粗暴的做法反而给出了出口电商绕过贸易战的一种逻辑:降低推售产品的价格敏感性,多关注那些高质高价的产品。越&屌丝&的产品,价格浮动越敏感是不争的事实,红米手机从599到699有很大的不同,iphoneX卖8000或者8500区别并不太大。近些年火热的消费升级其实是欧美最先发生,然后中国中产阶级跟上。欧美等国的消费需求逐渐从低价向品质延伸,消费过程中越来越看重商品的质量、品质乃至品牌的个性和文化背景,为更好的品质付费也开始被消费者所接受。从这个意义上说,除了品牌要借助平台塑造自己的形象,平台也必须反过来要求品牌商们保证&品质力&,降低低端、价格敏感产品的准入。新蛋开招商会的同时,联络互动MOPS品牌同步发布了&全场景&无线充电产品,在厚度、总量、外观设计等方面走高端路线刷新常规无线充电的印象,说白了也是做个国货出海的产品示范,某种程度上是对新蛋品牌合作商产品的衡量准绳之一。出口电商或是区块链的恰当场景强调去中心化的区块链,从目前来看其有效的、有价值呈现而非花火一场的应用场景主要包括两类:1、传统互联网没有照顾到的,诸如在国家与国家支付的过程中,因为没有&地球中央银行&的存在,区块链变得尤为必要,例如最近新加坡中央银行确认使用区块链国际支付计划,Visa推出的基于区块链技术的国际B2B支付解决方案。2、过去互联网技术没有达到要求的,共享经济特别是非实物共享(区别于滴滴、ofo等实物共享),本来就带有去中心化要求,但技术却不能足够支撑。斐讯的天天链N1即是这个领域的案例。而出口电商面临的复杂供应商、渠道、支付、目的地环境等,是典型的缺乏中心化控制的商业领域,这类领域天然带有对区块链的需求。兰亭集势在如日中天时,成立了实验室研究&区块链+供应链&的双链合一应用,目的在于大幅提升消费者的物流体验在内的综合跨境网购体验。此外,虽然出口电商们对比特币支付态度各不相同,但这种去中心化的数字货币的确十分适合出口电商的支付,只是比特币本身波动太大、不够成熟导致应用仍然无法良好落地。而且,由于是全球货币,比特币(或者将来其他公认的数字货币)可以减少贸易壁垒合并汇率管制的影响,无疑是出口电商甚至其他涉及跨镜买卖的领域非常好的选择。只是,无论从出口电商本身的准备,还是区块链数字货币本身的成熟度来看,这一切都还需要相当长的时间。(完)文 | 曾响铃
24小时报不停
居家生活类短视频自媒体「意思生活」获千万融资
前抖音红人温婉微博直播回应“被封杀”,称低俗的我不做
以太坊又被爆重大漏洞,七成节点一度出现瘫痪风险
削减成本增加10%技术投入,爱立信欲借5G复苏
Boss直聘CEO赵鹏:世界杯广告花了一个多亿,这一步很冒险
痛失小型在线药店PillPack,沃尔玛市值蒸发30亿美元
共享电动滑板公司Bird四个月融资4亿美元,估值超20亿美元
百度王海峰:AI赋能软件开发将提高程序员工作效率
盟科医药正式向港交所递交上市申请 ,首款药物有望2020年上市
亚马逊宣布两条消息致8家公司市值单日蒸发175亿美元
汤森路透报告:40%的机构投资者将提高在AI方面预算
OPPO公布Find X中国价格:兰博基尼版9999元
荣耀手机宣布进军拉丁美洲,首站落地哥伦比亚
观脉科技完成B轮1亿元融资,构建全球高速专用网络
工信部:取消流量“漫游”费7月1日起正式实施
途家称获日本政府民宿预订资质,将上线保险业务
奥组委将于7月举办电竞论坛,讨论电竞是否加入奥运会
谷歌首次承认竞购GitHub输给了微软
大唐电信与腾讯公司签署5G战略合作框架协议书
新漏洞曝光:可影响2012年以来几乎所有安卓设备
大连万达旗下传奇影业公司募集10亿美元
阿里注资300亿发展游戏?阿里游戏:纯属谣言!
滴滴外卖将上线第5个城市,7月进军郑州
阿里巴巴决定投资土耳其电商Trendyol,具体金额不详
陈睿:B站不会去二次元化,尽量包容各种不同爱好
中兴总裁赵先明:禁令解除后很短时间将恢复正常
儿童托育连锁品牌袋鼠麻麻完成数千万元A轮融资,光速中国领投
传今日头条做游戏直播,西瓜:内容覆盖全品类
猎聘上市,创始人戴科彬怕员工自满松懈
巴黎市长与摩拜ofo等签章程:行驶停放不得妨碍行人如何将高并发拉下神坛!
“ 高并发也算是这几年的热门词汇了,尤其在互联网圈,开口不聊个高并发问题,都不好意思出门。高并发有那么邪乎吗?动不动就千万并发、亿级流量,听上去的确挺吓人。但仔细想想,这么大的并发与流量不都是通过路由器来的吗?一切源自网卡高并发的流量通过低调的路由器进入我们系统,第一道关卡就是网卡,网卡怎么抗住高并发?这个问题压根就不存在,千万并发在网卡看来,一样一样的,都是电信号,网卡眼里根本区分不出来你是千万并发还是一股洪流,所以衡量网卡牛不牛都说带宽,从来没有并发量的说法。网卡位于物理层和链路层,最终把数据传递给网络层(IP 层),在网络层有了 IP 地址,已经可以识别出你是千万并发了。所以搞网络层的可以自豪的说,我解决了高并发问题,可以出来吹吹牛了。谁没事搞网络层呢?主角就是路由器,这玩意主要就是玩儿网络层。一头雾水非专业的我们,一般都把网络层(IP 层)和传输层(TCP 层)放到一起,操作系统提供,对我们是透明的,很低调、很靠谱,以至于我们都把它忽略了。吹过的牛是从应用层开始的,应用层一切都源于 Socket,那些千万并发最终会经过传输层变成千万个 Socket,那些吹过的牛,不过就是如何快速处理这些 Socket。处理 IP 层数据和处理 Socket 究竟有啥不同呢?没有连接,就没有等待最重要的一个不同就是 IP 层不是面向连接的,而 Socket 是面向连接的。IP 层没有连接的概念,在 IP 层,来一个数据包就处理一个,不用瞻前也不用顾后。而处理 Socket,必须瞻前顾后,Socket 是面向连接的,有上下文的,读到一句我爱你,激动半天,你不前前后后地看看,就是瞎激动了。你想前前后后地看明白,就要占用更多的内存去记忆,就要占用更长的时间去等待;不同连接要搞好隔离,就要分配不同的线程(或者协程)。所有这些都解决好,貌似还是有点难度的。感谢操作系统操作系统是个好东西,在 Linux 系统上,所有的 IO 都被抽象成了文件,网络 IO 也不例外,被抽象成 Socket。但是 Socket 还不仅是一个 IO 的抽象,它同时还抽象了如何处理 Socket,最著名的就是 select 和 epoll 了。知名的 Nginx、Netty、Redis 都是基于 epoll 做的,这仨家伙基本上是在千万并发领域的必备神技。但是多年前,Linux 只提供了 select,这种模式能处理的并发量非常小,而 epoll 是专为高并发而生的,感谢操作系统。不过操作系统没有解决高并发的所有问题,只是让数据快速地从网卡流入我们的应用程序,如何处理才是老大难。操作系统的使命之一就是最大限度的发挥硬件的能力,解决高并发问题,这也是最直接、最有效的方案,其次才是分布式计算。前面我们提到的 Nginx、Netty、Redis 都是最大限度发挥硬件能力的典范。如何才能最大限度的发挥硬件能力呢?核心矛盾要最大限度的发挥硬件能力,首先要找到核心矛盾所在。我认为,这个核心矛盾从计算机诞生之初直到现在,几乎没有发生变化,就是 CPU 和 IO 之间的矛盾。CPU 以摩尔定律的速度野蛮发展,而 IO 设备(磁盘,网卡)却乏善可陈。龟速的 IO 设备成为性能瓶颈,必然导致 CPU 的利用率很低,所以提升 CPU 利用率几乎成了发挥硬件能力的代名词。中断与缓存CPU 与 IO 设备的协作基本都是以中断的方式进行的,例如读磁盘的操作,CPU 仅仅是发一条读磁盘到内存的指令给磁盘驱动,之后就立即返回了。此时 CPU 可以接着干其他事情,读磁盘到内存本身是个很耗时的工作,等磁盘驱动执行完指令,会发个中断请求给 CPU,告诉 CPU 任务已经完成,CPU 处理中断请求,此时 CPU 可以直接操作读到内存的数据。中断机制让 CPU 以最小的代价处理 IO 问题,那如何提高设备的利用率呢?答案就是缓存。操作系统内部维护了 IO 设备数据的缓存,包括读缓存和写缓存。读缓存很容易理解,我们经常在应用层使用缓存,目的就是尽量避免产生读 IO。写缓存应用层使用的不多,操作系统的写缓存,完全是为了提高 IO 写的效率。操作系统在写 IO 的时候会对缓存进行合并和调度,例如写磁盘会用到电梯调度算法。高效利用网卡高并发问题首先要解决的是如何高效利用网卡。网卡和磁盘一样,内部也是有缓存的,网卡接收网络数据,先存放到网卡缓存,然后写入操作系统的内核空间(内存),我们的应用程序则读取内存中的数据,然后处理。除了网卡有缓存外,TCP/IP 协议内部还有发送缓冲区和接收缓冲区以及 SYN 积压队列、accept 积压队列。这些缓存,如果配置不合适,则会出现各种问题。例如在 TCP 建立连接阶段,如果并发量过大,而 Nginx 里面 Socket 的 backlog 设置的值太小,就会导致大量连接请求失败。如果网卡的缓存太小,当缓存满了后,网卡会直接把新接收的数据丢掉,造成丢包。当然如果我们的应用读取网络 IO 数据的效率不高,会加速网卡缓存数据的堆积。如何高效读取网络数据呢?目前在 Linux 上广泛应用的就是 epoll 了。操作系统把 IO 设备抽象为文件,网络被抽象成了 Socket,Socket 本身也是一个文件,所以可以用 read/write 方法来读取和发送网络数据。在高并发场景下,如何高效利用 Socket 快速读取和发送网络数据呢?要想高效利用 IO,就必须在操作系统层面了解 IO 模型,在《UNIX网络编程》这本经典著作里总结了五种 IO 模型,分别是:阻塞式 IO非阻塞式 IO多路复用 IO信号驱动 IO异步 IO阻塞式 IO我们以读操作为例,当我们调用 read 方法读取 Socket 上的数据时,如果此时 Socket 读缓存是空的(没有数据从 Socket 的另一端发过来),操作系统会把调用 read 方法的线程挂起,直到 Socket 读缓存里有数据时,操作系统再把该线程唤醒。当然,在唤醒的同时,read 方法也返回了数据。我理解所谓的阻塞,就是操作系统是否会挂起线程。非阻塞式 IO而对于非阻塞式 IO,如果 Socket 的读缓存是空的,操作系统并不会把调用 read 方法的线程挂起,而是立即返回一个 EAGAIN 的错误码。在这种情景下,可以轮询 read 方法,直到 Socket 的读缓存有数据则可以读到数据,这种方式的缺点非常明显,就是消耗大量的 CPU。多路复用 IO对于阻塞式 IO,由于操作系统会挂起调用线程,所以如果想同时处理多个 Socket,就必须相应地创建多个线程。线程会消耗内存,增加操作系统进行线程切换的负载,所以这种模式不适合高并发场景。有没有办法较少线程数呢?非阻塞 IO 貌似可以解决,在一个线程里轮询多个 Socket,看上去可以解决线程数的问题,但实际上这个方案是无效的。原因是调用 read 方法是一个系统调用,系统调用是通过软中断实现的,会导致进行用户态和内核态的切换,所以很慢。但是这个思路是对的,有没有办法避免系统调用呢?有,就是多路复用 IO。在 Linux 系统上 select/epoll 这俩系统 API 支持多路复用 IO,通过这两个 API,一个系统调用可以监控多个 Socket,只要有一个 Socket 的读缓存有数据了,方法就立即返回。然后你就可以去读这个可读的 Socket 了,如果所有的 Socket 读缓存都是空的,则会阻塞,也就是将调用 select/epoll 的线程挂起。所以 select/epoll 本质上也是阻塞式 IO,只不过它们可以同时监控多个 Socket。
select 和 epoll 的区别为什么多路复用 IO 模型有两个系统 API?我分析原因是,select 是 POSIX 标准中定义的,但是性能不够好,所以各个操作系统都推出了性能更好的 API,如 Linux 上的 epoll、Windows 上的 IOCP。至于 select 为什么会慢,大家比较认可的原因有两点:一点是 select 方法返回后,需要遍历所有监控的 Socket,而不是发生变化的 Socket。还有一点是每次调用 select 方法,都需要在用户态和内核态拷贝文件描述符的位图(通过调用三次 copy_from_user 方法拷贝读、写、异常三个位图)。epoll 可以避免上面提到的这两点。
Reactor 多线程模型在 Linux 操作系统上,性能最为可靠、稳定的 IO 模式就是多路复用,我们的应用如何能够利用好多路复用 IO 呢?经过前人多年实践总结,搞了一个 Reactor 模式,目前应用非常广泛,著名的 Netty、Tomcat NIO 就是基于这个模式。Reactor 的核心是事件分发器和事件处理器,事件分发器是连接多路复用 IO 和网络数据处理的中枢,监听 Socket 事件(select/epoll_wait)。然后将事件分发给事件处理器,事件分发器和事件处理器都可以基于线程池来做。需要重点提一下的是,在 Socket 事件中主要有两大类事件,一个是连接请求,另一个是读写请求,连接请求成功处理之后会创建新的 Socket,读写请求都是基于这个新创建的 Socket。所以在网络处理场景中,实现 Reactor 模式会稍微有点绕,但是原理没有变化。具体实现可以参考 Doug Lea 的《Scalable IO in Java》(http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf)。Reactor 原理图
Nginx 多进程模型Nginx 默认采用的是多进程模型,Nginx 分为 Master 进程和 Worker 进程。真正负责监听网络请求并处理请求的只有 Worker 进程,所有的 Worker 进程都监听默认的 80 端口,但是每个请求只会被一个 Worker 进程处理。这里面的玄机是:每个进程在 accept 请求前必须争抢一把锁,得到锁的进程才有权处理当前的网络请求。每个 Worker 进程只有一个主线程,单线程的好处是无锁处理,无锁处理并发请求,这基本上是高并发场景里面的最高境界了。(参考http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf)数据经过网卡、操作系统、网络协议中间件(Tomcat、Netty 等)重重关卡,终于到了我们应用开发人员手里,我们如何处理这些高并发的请求呢?我们还是先从提升单机处理能力的角度来思考这个问题。
突破木桶理论我们还是先从提升单机处理能力的角度来思考这个问题,在实际应用的场景中,问题的焦点是如何提高 CPU 的利用率(谁叫它发展的最快呢)。木桶理论讲最短的那根板决定水位,那为啥不是提高短板 IO 的利用率,而是去提高 CPU 的利用率呢?这个问题的答案是在实际应用中,提高了 CPU 的利用率往往会同时提高 IO 的利用率。当然在 IO 利用率已经接近极限的条件下,再提高 CPU 利用率是没有意义的。我们先来看看如何提高 CPU 的利用率,后面再看如何提高 IO 的利用率。
并行与并发提升 CPU 利用率目前主要的方法是利用 CPU 的多核进行并行计算,并行和并发是有区别的。在单核 CPU 上,我们可以一边听 MP3,一边 Coding,这个是并发,但不是并行,因为在单核 CPU 的视野,听 MP3 和 Coding 是不可能同时进行的。只有在多核时代,才会有并行计算。并行计算这东西太高级,工业化应用的模型主要有两种,一种是共享内存模型,另外一种是消息传递模型。
多线程设计模式对于共享内存模型,其原理基本都来自大师 Dijkstra 在半个世纪前(1965)的一篇论文《Cooperating sequential processes》。这篇论文提出了大名鼎鼎的概念信号量,Java 里面用于线程同步的 wait/notify 也是信号量的一种实现。大师的东西看不懂,学不会也不用觉得丢人,毕竟大师的嫡传子弟也没几个。东洋有个叫结城浩的总结了一下多线程编程的经验,写了本书叫《JAVA多线程设计模式》,这个还是挺接地气(能看懂)的,下面简单介绍一下。Single Threaded Execution这个模式是把多线程变成单线程,多线程在同时访问一个变量时,会发生各种莫名其妙的问题,这个设计模式直接把多线程搞成了单线程,于是安全了,当然性能也就下来了。最简单的实现就是利用 synchronized 将存在安全隐患的代码块(方法)保护起来。在并发领域有个临界区(criticalsections)的概念,我感觉和这个模式是一回事。Immutable Pattern如果共享变量永远不变,那多个线程访问就没有任何问题,永远安全。这个模式虽然简单,但是用的好,能解决很多问题。Guarded Suspension Patten这个模式其实就是等待-通知模型,当线程执行条件不满足时,挂起当前线程(等待);当条件满足时,唤醒所有等待的线程(通知),在 Java 语言里利用 synchronized,wait/notifyAll 可以很快实现一个等待通知模型。结城浩将这个模式总结为多线程版的 If,我觉得非常贴切。Balking这个模式和上个模式类似,不同点是当线程执行条件不满足时直接退出,而不是像上个模式那样挂起。这个用法最大的应用场景是多线程版的单例模式,当对象已经创建了(不满足创建对象的条件)就不用再创建对象(退出)。Producer-Consumer生产者-消费者模式,全世界人都知道。我接触的最多的是一个线程处理 IO(如查询数据库),一个(或者多个)线程处理 IO 数据,这样 IO 和 CPU 就都能充分利用起来。如果生产者和消费者都是 CPU 密集型,再搞生产者-消费者就是自己给自己找麻烦了。Read-Write Lock读写锁解决的是读多写少场景下的性能问题,支持并行读,但是写操作只允许一个线程做。如果写操作非常非常少,而读的并发量非常非常大,这个时候可以考虑使用写时复制(copy on write)技术,我个人觉得应该单独把写时复制作为一个模式。Thread-Per-Message就是我们经常提到的一请求一线程。Worker Thread一请求一线程的升级版,利用线程池解决线程的频繁创建、销毁导致的性能问题。BIO 年代 Tomcat 就是用的这种模式。Future当你调用某个耗时的同步方法很心烦,想同时干点别的事情,可以考虑用这个模式,这个模式的本质是个同步变异步的转换器。同步之所以能变异步,本质上是启动了另外一个线程,所以这个模式和一请求一线程还是多少有点关系的。Two-Phase Termination这个模式能解决优雅地终止线程的需求。Thread-Specific Storage线程本地存储,避免加锁、解锁开销的利器,C# 里面有个支持并发的容器 ConcurrentBag 就是采用了这个模式。这个星球上最快的数据库连接池 HikariCP 借鉴了 ConcurrentBag 的实现,搞了个 Java 版的,有兴趣的同学可以参考。Active Object(这个不讲也罢)这个模式相当于降龙十八掌的最后一掌,综合了前面的设计模式,有点复杂,个人觉得借鉴的意义大于参考实现。最近国人也出过几本相关的书,但总体还是结城浩这本更能经得住推敲。基于共享内存模型解决并发问题,主要问题就是用好锁。但是用好锁,还是有难度的,所以后来又有人搞了消息传递模型。
消息传递模型共享内存模型难度还是挺大的,而且你没有办法从理论上证明写的程序是正确的,我们总一不小心就会写出来个死锁的程序来,每当有了问题,总会有大师出来。于是消息传递(Message-Passing)模型横空出世(发生在上个世纪 70 年代),消息传递模型有两个重要的分支,一个是 Actor 模型,一个是 CSP 模型。Actor 模型Actor 模型因为 Erlang 声名鹊起,后来又出现了 Akka。在 Actor 模型里面,没有操作系统里所谓进程、线程的概念,一切都是 Actor,我们可以把 Actor 想象成一个更全能、更好用的线程。在 Actor 内部是线性处理(单线程)的,Actor 之间以消息方式交互,也就是不允许 Actor 之间共享数据。没有共享,就无需用锁,这就避免了锁带来的各种副作用。Actor 的创建和 new 一个对象没有啥区别,很快、很小,不像线程的创建又慢又耗资源。Actor 的调度也不像线程会导致操作系统上下文切换(主要是各种寄存器的保存、恢复),所以调度的消耗也很小。Actor 还有一个有点争议的优点,Actor 模型更接近现实世界,现实世界也是分布式的、异步的、基于消息的、尤其 Actor 对于异常(失败)的处理、自愈、监控等都更符合现实世界的逻辑。但是这个优点改变了编程的思维习惯,我们目前大部分编程思维习惯其实是和现实世界有很多差异的。一般来讲,改变我们思维习惯的事情,阻力总是超乎我们的想象。CSP 模型Golang 在语言层面支持 CSP 模型,CSP 模型和 Actor 模型的一个感官上的区别是在 CSP 模型里面,生产者(消息发送方)和消费者(消息接收方)是完全松耦合的,生产者完全不知道消费者的存在。但是在 Actor 模型里面,生产者必须知道消费者,否则没办法发送消息。CSP 模型类似于我们在多线程里面提到的生产者-消费者模型,核心的区别我觉得在于 CSP 模型里面有类似绿色线程(green thread)的东西。绿色线程在 Golang 里面叫做协程,协程同样是个非常轻量级的调度单元,可以快速创建而且资源占用很低。Actor 在某种程度上需要改变我们的思维方式,而 CSP 模型貌似没有那么大动静,更容易被现在的开发人员接受,都说 Golang 是工程化的语言,在 Actor 和 CSP 的选择上,也可以看到这种体现。
多样世界除了消息传递模型,还有事件驱动模型、函数式模型。事件驱动模型类似于观察者模式,在 Actor 模型里面,消息的生产者必须知道消费者才能发送消息、而在事件驱动模型里面,事件的消费者必须知道消息的生产者才能注册事件处理逻辑。Akka 里消费者可以跨网络,事件驱动模型的具体实现如 Vertx 里,消费者也可以订阅跨网络的事件,从这个角度看,大家都在取长补短。点击图片查看更多推荐内容↓↓↓跟着动画学习TCP三次握手和四次挥手!从京东618秒杀聊聊秒杀限流的多种实现!中小企业对Spring Cloud微服务的一些思考!开发中我们需要遵循的几个设计原则!
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!

我要回帖

更多关于 玩游戏盒 是什么进程 的文章

 

随机推荐