沧州三亚菏泽经济预测自然
投稿投诉
自然科学
知识物理
化学生物
地理解释
预测理解
本质社会
人类现象
行为研究
经济政治
心理结构
关系指导
人文遗产
菏泽德阳
山西湖州
宝鸡上海
茂名内江
三亚信阳
长春北海
西安安徽
黄石烟台
沧州湛江
肇庆鹤壁
六安韶关
成都钦州

高铁12306的编程架构到底有多牛逼?

7月3日 九阙忬投稿
  大家好,我是柠檬哥,专注编程知识分享。
  欢迎关注程序员柠檬橙,编程路上不迷路,私信发送以下关键字获取编程资源:
  发送1024打包下载10个G编程资源学习资料
  发送001获取阿里大神LeetCode刷题笔记
  发送002获取获取谷歌公司编程代码规范
  发送003获取10个精美简历模板PDF和Word版
  发送004获取100道精选C面试题和答案word版
  发送005获取获取谷歌LeetCode算法笔记
  最近看到一篇关于12306架构优化和演进的文章,介绍了12306是如何在全国人民的压测中不断进化的:
  要知道12306网站仅在2015年春运高峰日处理了超过180亿次车票查询服务,平均TPS超过30万次s。
  另外12306系统的复杂之处就在于,它的SKU(即StockkeepingUnit,库存保有单位)并不像一般电商网站那样,可以通过区别货品有和没有来简单计算,而是需要结合每条线路的不同区间来做复杂运算,并且,12306的SKU还是时刻动态变化着的。
  12306抢票,极限并发带来的思考
  虽然现在大多数情况下都能订到票,但是放票瞬间即无票的场景,相信大家都深有体会。
  尤其是春节期间,大家不仅使用12306,还会考虑智行和其他的抢票软件,全国上下几亿人在这段时间都在抢票。
  12306服务承受着这个世界上任何秒杀系统都无法超越的QPS,上百万的并发再正常不过了!
  笔者专门研究了一下12306的服务端架构,学习到了其系统设计上很多亮点,在这里和大家分享一下并模拟一个例子:如何在100万人同时抢1万张火车票时,系统提供正常、稳定的服务
  高并发的系统架构都会采用分布式集群部署,服务上层有着层层负载均衡,并提供各种容灾手段(双火机房、节点容错、服务器灾备等)保证系统的高可用,流量也会根据不同的负载能力和配置策略均衡到不同的服务器上。
  下边是一个简单的示意图:
  负载均衡简介
  上图中描述了用户请求到服务器经历了三层的负载均衡,下边分别简单介绍一下这三种负载均衡。
  OSPF(开放式最短链路优先)是一个内部网关协议(InteriorGatewayProtocol,简称IGP)
  OSPF通过路由器之间通告网络接口的状态来建立链路状态数据库,生成最短路径树,OSPF会自动计算路由接口上的Cost值,但也可以通过手工指定该接口的Cost值,手工指定的优先于自动计算机值。
  OSPF计算的Cost,同样是和接口带宽成反比,带宽越高,Cost值越小。到达目标相同Cost值的路径,可以执行负载均衡,最多6条链路同时执行负载均衡。
  LVS(LinuxVirtualServer)
  它是一种集群(Cluster)技术,采用IP负载均衡技术和基于内容请求分发技术。
  调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。
  Nginx
  想必大家都很熟悉了,是一款非常高性能的HTTP代理反向代理服务器,服务开发中也经常使用它来做负载均衡。
  Nginx实现负载均衡的方式主要有三种:轮询加权轮询IPHash轮询
  下面我们就针对Nginx的加权轮询做专门的配置和测试。Nginx加权轮询的演示
  Nginx实现负载均衡通过Upstream模块实现,其中加权轮询的配置是可以给相关的服务加上一个权重值,配置的时候可能根据服务器的性能、负载能力设置相应的负载。
  下面是一个加权轮询负载的配置,我将在本地的监听30013004端口,分别配置1,2,3,4的权重:配置负载均衡upstreamloadrule{server127。0。0。1:3001weight1;server127。0。0。1:3002weight2;server127。0。0。1:3003weight3;server127。0。0。1:3004weight4;}。。。server{listen80;servernameloadbalance。comwww。loadbalance。location{proxypasshttp:}
  我在本地etchosts目录下配置了www。loadbalance。com的虚拟域名地址。
  接下来使用Go语言开启四个HTTP端口监听服务,下面是监听在3001端口的Go程序,其他几个只需要修改端口即可:packagemainimport(nethttposstrings)funcmain(){http。HandleFunc(buyticket,handleReq)http。ListenAndServe(:3001,nil)}处理请求函数,根据请求将响应结果信息写入ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志afunchandleReq(whttp。ResponseWriter,rhttp。Request){failedMsg:handleinport:writeLog(failedMsg,。stat。log)}写入ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志afuncwriteLog(msgstring,logPathstring){fd,:os。OpenFile(logPath,os。ORDWRos。OCREATEos。OAPPEND,0644)deferfd。Close()content:strings。Join(〔〕string{msg,r},3001)buf:〔〕byte(content)fd。Write(buf)}
  我将请求的端口日志信息写到了。stat。log文件当中,然后使用AB压测工具做压测:abn1000c100http:www。loadbalance。combuyticket
  统计日志中的结果,30013004端口分别得到了100、200、300、400的请求量。
  这和我在Nginx中配置的权重占比很好地吻合在了一起,并且负载后的流量非常的均匀、随机。
  具体的实现大家可以参考Nginx的Upsteam模块实现源码,这里推荐一篇文章《Nginx中Upstream机制的负载均衡》:https:www。kancloud。cndigestunderstandingnginx202607秒杀抢购系统选型
  回到我们最初提到的问题中来:火车票秒杀系统如何在高并发情况下提供正常、稳定的服务呢?
  从上面的介绍我们知道用户秒杀流量通过层层的负载均衡,均匀到了不同的服务器上,即使如此,集群中的单机所承受的QPS也是非常高的。如何将单机性能优化到极致呢?
  要解决这个问题,我们就要想明白一件事:通常订票系统要处理生成订单、减扣库存、用户支付这三个基本的阶段。
  我们系统要做的事情是要保证火车票订单不超卖、不少卖,每张售卖的车票都必须支付才有效,还要保证系统承受极高的并发。
  这三个阶段的先后顺序该怎么分配才更加合理呢?我们来分析一下:下单减库存
  当用户并发请求到达服务端时,首先创建订单,然后扣除库存,等待用户支付。
  这种顺序是我们一般人首先会想到的解决方案,这种情况下也能保证订单不会超卖,因为创建订单之后就会减库存,这是一个原子操作。
  但是这样也会产生一些问题:在极限并发情况下,任何一个内存操作的细节都至关影响性能,尤其像创建订单这种逻辑,一般都需要存储到磁盘数据库的,对数据库的压力是可想而知的。如果用户存在恶意下单的情况,只下单不支付这样库存就会变少,会少卖很多订单,虽然服务端可以限制IP和用户的购买订单数量,这也不算是一个好方法。支付减库存
  如果等待用户支付了订单在减库存,第一感觉就是不会少卖。但是这是并发架构的大忌,因为在极限并发情况下,用户可能会创建很多订单。
  当库存减为零的时候很多用户发现抢到的订单支付不了了,这也就是所谓的超卖。也不能避免并发操作数据库磁盘IO。预扣库存
  从上边两种方案的考虑,我们可以得出结论:只要创建订单,就要频繁操作数据库IO。
  那么有没有一种不需要直接操作数据库IO的方案呢,这就是预扣库存。先扣除了库存,保证不超卖,然后异步生成用户订单,这样响应给用户的速度就会快很多;那么怎么保证不少卖呢?用户拿到了订单,不支付怎么办?
  我们都知道现在订单都有有效期,比如说用户五分钟内不支付,订单就失效了,订单一旦失效,就会加入新的库存,这也是现在很多网上零售企业保证商品不少卖采用的方案。
  订单的生成是异步的,一般都会放到MQ、Kafka这样的即时消费队列中处理,订单量比较少的情况下,生成订单非常快,用户几乎不用排队。扣库存的艺术
  从上面的分析可知,显然预扣库存的方案最合理。我们进一步分析扣库存的细节,这里还有很大的优化空间,库存存在哪里?怎样保证高并发下,正确的扣库存,还能快速的响应用户请求?
  在单机低并发情况下,我们实现扣库存通常是这样的:
  为了保证扣库存和生成订单的原子性,需要采用事务处理,然后取库存判断、减库存,最后提交事务,整个流程有很多IO,对数据库的操作又是阻塞的。
  这种方式根本不适合高并发的秒杀系统。接下来我们对单机扣库存的方案做优化:本地扣库存。
  我们把一定的库存量分配到本地机器,直接在内存中减库存,然后按照之前的逻辑异步创建订单。
  改进过之后的单机系统是这样的:
  这样就避免了对数据库频繁的IO操作,只在内存中做运算,极大的提高了单机抗并发的能力。
  但是百万的用户请求量单机是无论如何也抗不住的,虽然Nginx处理网络请求使用Epoll模型,c10k的问题在业界早已得到了解决。
  但是Linux系统下,一切资源皆文件,网络请求也是这样,大量的文件描述符会使操作系统瞬间失去响应。
  上面我们提到了Nginx的加权均衡策略,我们不妨假设将100W的用户请求量平均均衡到100台服务器上,这样单机所承受的并发量就小了很多。
  然后我们每台机器本地库存100张火车票,100台服务器上的总库存还是1万,这样保证了库存订单不超卖,下面是我们描述的集群架构:
  问题接踵而至,在高并发情况下,现在我们还无法保证系统的高可用,假如这100台服务器上有两三台机器因为扛不住并发的流量或者其他的原因宕机了。那么这些服务器上的订单就卖不出去了,这就造成了订单的少卖。
  要解决这个问题,我们需要对总订单量做统一的管理,这就是接下来的容错方案。服务器不仅要在本地减库存,另外要远程统一减库存。
  有了远程统一减库存的操作,我们就可以根据机器负载情况,为每台机器分配一些多余的Buffer库存用来防止机器中有机器宕机的情况。
  我们结合下面架构图具体分析一下:
  我们采用Redis存储统一库存,因为Redis的性能非常高,号称单机QPS能抗10W的并发。
  在本地减库存以后,如果本地有订单,我们再去请求Redis远程减库存,本地减库存和远程减库存都成功了,才返回给用户抢票成功的提示,这样也能有效的保证订单不会超卖。
  当机器中有机器宕机时,因为每个机器上有预留的Buffer余票,所以宕机机器上的余票依然能够在其他机器上得到弥补,保证了不少卖。
  Buffer余票设置多少合适呢,理论上Buffer设置的越多,系统容忍宕机的机器数量就越多,但是Buffer设置的太大也会对Redis造成一定的影响。
  虽然Redis内存数据库抗并发能力非常高,请求依然会走一次网络IO,其实抢票过程中对Redis的请求次数是本地库存和Buffer库存的总量。
  因为当本地库存不足时,系统直接返回用户已售罄的信息提示,就不会再走统一扣库存的逻辑。
  这在一定程度上也避免了巨大的网络请求量把Redis压跨,所以Buffer值设置多少,需要架构师对系统的负载能力做认真的考量。代码演示
  Go语言原生为并发设计,我采用Go语言给大家演示一下单机抢票的具体流程。初始化工作
  Go包中的Init函数先于Main函数执行,在这个阶段主要做一些准备性工作。
  我们系统需要做的准备工作有:初始化本地库存、初始化远程Redis存储统一库存的Hash键值、初始化Redis连接池。
  另外还需要初始化一个大小为1的Int类型Chan,目的是实现分布式锁的功能。
  也可以直接使用读写锁或者使用Redis等其他的方式避免资源竞争,但使用Channel更加高效,这就是Go语言的哲学:不要通过共享内存来通信,而要通过通信来共享内存。
  Redis库使用的是Redigo,下面是代码实现:。。。localSpike包结构体定义packagelocalSpiketypeLocalSpikestruct{LocalInStockint64LocalSalesVolumeint64}。。。remoteSpike对hash结构的定义和redis连接池packageremoteSpike远程订单存储健值typeRemoteSpikeKeysstruct{SpikeOrderHashKeystringredis中秒杀订单hash结构keyTotalInventoryKeystringhash结构中总订单库存keyQuantityOfOrderKeystringhash结构中已有订单数量key}初始化redis连接池funcNewPool()redis。Pool{returnredis。Pool{MaxIdle:10000,MaxActive:12000,maxnumberofconnectionsDial:func()(redis。Conn,error){c,err:redis。Dial(tcp,:6379)iferr!nil{panic(err。Error())}returnc,err},}}。。。funcinit(){localSpikelocalSpike2。LocalSpike{LocalInStock:150,LocalSalesVolume:0,}remoteSpikeremoteSpike2。RemoteSpikeKeys{SpikeOrderHashKey:tickethashkey,TotalInventoryKey:tickettotalnums,QuantityOfOrderKey:ticketsoldnums,}redisPoolremoteSpike2。NewPool()donemake(chanint,1)done1}本地扣库存和统一扣库存
  本地扣库存逻辑非常简单,用户请求过来,添加销量,然后对比销量是否大于本地库存,返回Bool值:packagelocalSpike本地扣库存,返回bool值func(spikeLocalSpike)LocalDeductionStock()bool{spike。LocalSalesVolumespike。LocalSalesVolume1returnspike。LocalSalesVolumespike。LocalInStock}
  注意这里对共享数据LocalSalesVolume的操作是要使用锁来实现的,但是因为本地扣库存和统一扣库存是一个原子性操作,所以在最上层使用Channel来实现,这块后边会讲。
  统一扣库存操作Redis,因为Redis是单线程的,而我们要实现从中取数据,写数据并计算一些列步骤,我们要配合Lua脚本打包命令,保证操作的原子性:packageremoteSpike。。。。。。constLuaScriptlocalticketkeyKEYS〔1〕localtickettotalkeyARGV〔1〕localticketsoldkeyARGV〔2〕localtickettotalnumstonumber(redis。call(HGET,ticketkey,tickettotalkey))localticketsoldnumstonumber(redis。call(HGET,ticketkey,ticketsoldkey))查看是否还有余票,增加订单数量,返回结果值if(tickettotalnumsticketsoldnums)thenreturnredis。call(HINCRBY,ticketkey,ticketsoldkey,1)endreturn0远端统一扣库存func(RemoteSpikeKeysRemoteSpikeKeys)RemoteDeductionStock(connredis。Conn)bool{lua:redis。NewScript(1,LuaScript)result,err:redis。Int(lua。Do(conn,RemoteSpikeKeys。SpikeOrderHashKey,RemoteSpikeKeys。TotalInventoryKey,RemoteSpikeKeys。QuantityOfOrderKey))iferr!nil{returnfalse}returnresult!0}
  我们使用Hash结构存储总库存和总销量的信息,用户请求过来时,判断总销量是否大于库存,然后返回相关的Bool值。
  在启动服务之前,我们需要初始化Redis的初始库存信息:hmsettickethashkeytickettotalnums10000ticketsoldnums0响应用户信息
  我们开启一个HTTP服务,监听在一个端口上:packagemain。。。funcmain(){http。HandleFunc(buyticket,handleReq)http。ListenAndServe(:3005,nil)}
  上面我们做完了所有的初始化工作,接下来handleReq的逻辑非常清晰,判断是否抢票成功,返回给用户信息就可以了。packagemain处理请求函数,根据请求将响应结果信息写入ahrefhttps:www。bs178。comrizhitargetblankclassinfotextkey日志afunchandleReq(whttp。ResponseWriter,rhttp。Request){redisConn:redisPool。Get()LogMsg:done全局读写锁iflocalSpike。LocalDeductionStock()remoteSpike。RemoteDeductionStock(redisConn){util。RespJson(w,1,抢票成功,nil)LogMsgLogMsgresult:1,localSales:strconv。FormatInt(localSpike。LocalSalesVolume,10)}else{util。RespJson(w,1,已售罄,nil)LogMsgLogMsgresult:0,localSales:strconv。FormatInt(localSpike。LocalSalesVolume,10)}done1将抢票状态写入到log中writeLog(LogMsg,。stat。log)}funcwriteLog(msgstring,logPathstring){fd,:os。OpenFile(logPath,os。ORDWRos。OCREATEos。OAPPEND,0644)deferfd。Close()content:strings。Join(〔〕string{msg,r},)buf:〔〕byte(content)fd。Write(buf)}
  前边提到我们扣库存时要考虑竞态条件,我们这里是使用Channel避免并发的读写,保证了请求的高效顺序执行。我们将接口的返回信息写入到了。stat。log文件方便做压测统计。单机服务压测
  开启服务,我们使用AB压测工具进行测试:abn10000c100http:127。0。0。1:3005buyticket
  下面是我本地低配Mac的压测信息:ThisisApacheBench,Version2。3revision:1826891Copyright1996AdamTwiss,ZeusTechnologyLtd,http:www。zeustech。netLicensedtoTheApacheSoftwareFoundation,http:www。apache。orgBenchmarking127。0。0。1(bepatient)Completed1000requestsCompleted2000requestsCompleted3000requestsCompleted4000requestsCompleted5000requestsCompleted6000requestsCompleted7000requestsCompleted8000requestsCompleted9000requestsCompleted10000requestsFinished10000requestsServerSoftware:ServerHostname:127。0。0。1ServerPort:3005DocumentPath:buyticketDocumentLength:29bytesConcurrencyLevel:100Timetakenfortests:2。339secondsCompleterequests:10000Failedrequests:0Totaltransferred:1370000bytesHTMLtransferred:290000bytesRequestspersecond:4275。96〔sec〕(mean)Timeperrequest:23。387〔ms〕(mean)Timeperrequest:0。234〔ms〕(mean,acrossallconcurrentrequests)Transferrate:572。08〔Kbytessec〕receivedConnectionTimes(ms)minmean〔sd〕medianmaxConnect:0814。76223Processing:21517。611232Waiting:11113。58225Total:72322。818239Percentageoftherequestsservedwithinacertaintime(ms)50186624752680289033953998459954100239(longestrequest)
  根据指标显示,我单机每秒就能处理4000的请求,正常服务器都是多核配置,处理1W的请求根本没有问题。
  而且查看日志发现整个服务过程中,请求都很正常,流量均匀,Redis也很正常:stat。log。。。result:1,localSales:145result:1,localSales:146result:1,localSales:147result:1,localSales:148result:1,localSales:149result:1,localSales:150result:0,localSales:151result:0,localSales:152result:0,localSales:153result:0,localSales:154result:0,localSales:156。。。总结回顾
  总体来说,秒杀系统是非常复杂的。我们这里只是简单介绍模拟了一下单机如何优化到高性能,集群如何避免单点故障,保证订单不超卖、不少卖的一些策略
  完整的订单系统还有订单进度的查看,每台服务器上都有一个任务,定时的从总库存同步余票和库存信息展示给用户,还有用户在订单有效期内不支付,释放订单,补充到库存等等。
  我们实现了高并发抢票的核心逻辑,可以说系统设计的非常的巧妙,巧妙的避开了对DB数据库IO的操作。
  对Redis网络IO的高并发请求,几乎所有的计算都是在内存中完成的,而且有效的保证了不超卖、不少卖,还能够容忍部分机器的宕机。
  我觉得其中有两点特别值得学习总结:
  负载均衡,分而治之
  通过负载均衡,将不同的流量划分到不同的机器上,每台机器处理好自己的请求,将自己的性能发挥到极致。
  这样系统的整体也就能承受极高的并发了,就像工作的一个团队,每个人都将自己的价值发挥到了极致,团队成长自然是很大的。
  合理的使用并发和异步
  自Epoll网络架构模型解决了c10k问题以来,异步越来越被服务端开发人员所接受,能够用异步来做的工作,就用异步来做,在功能拆解上能达到意想不到的效果。
  这点在Nginx、Node。JS、Redis上都能体现,他们处理网络请求使用的Epoll模型,用实践告诉了我们单线程依然可以发挥强大的威力。
  服务器已经进入了多核时代,Go语言这种天生为并发而生的语言,完美的发挥了服务器多核优势,很多可以并发处理的任务都可以使用并发来解决,比如Go处理HTTP请求时每个请求都会在一个Goroutine中执行。
  总之,怎样合理地压榨CPU,让其发挥出应有的价值,是我们一直需要探索学习的方向。
  作者:掘金绘你一世倾城来源:https:juejin。impost5d84e21f6fb9a06ac8248149
  我是柠檬哥,专注编程知识分享。
  欢迎关注程序员柠檬橙,编程路上不迷路,私信发送以下关键字获取编程资源:
  发送1024打包下载10个G编程资源学习资料
  发送001获取阿里大神LeetCode刷题笔记
  发送002获取获取谷歌公司编程代码规范
  发送003获取10个精美简历模板PDF和Word版
  发送004获取100道精选C面试题和答案word版
  发送005获取获取谷歌LeetCode算法笔记
投诉 评论

快男出了15位明星,只有3位活下来,多人惨遭封杀近日,芒果台新出了一档综艺,嘉宾是07年的快男选手陈楚生,苏醒,王栎鑫等人。他们在节目中合唱了《少年》,一首歌、一群人,就把小8带回了那个用小灵通发短信为他们投票的少年时……周立波的三次婚姻,孩子却没一个是亲生的,但他仍乐在其中我曾经给所有夫妻一句忠告:坦坦荡荡过三日,遮遮掩掩过一生。说这话的人,是曾经的脱口秀名嘴,他在一次脱口秀中表达了自己的爱情观,更直接说道:男女之间的感情,也基本是靠谎言维……高铁12306的编程架构到底有多牛逼?大家好,我是柠檬哥,专注编程知识分享。欢迎关注程序员柠檬橙,编程路上不迷路,私信发送以下关键字获取编程资源:发送1024打包下载10个G编程资源学习资料发送0……有文化造句用有文化造句大全181,事实证明,仅有经济发达,只算“富而无骄”,要达到“富而好礼”的境界,还要有文化的繁荣、学术的进步和思想的开放。182,这招娣到男方家后,也上过几年学,算是断文识字……哪些食物最好不要隔夜吃?注重饮食安全问题,才能提供营养物质的同时远离疾病。有的人比较节省,吃剩下的东西大多会放到隔夜继续加热再吃,但是那些很在意饮食健康的人觉得食物二次加热就有安全隐患,特别是米饭,总……微信8。0。32双版本更新!新增9大功能,你升级了吗?最近,安卓、iOS微信相继推送了8。0。32新版本,本次更新带来了9个实用功能,下面一起来了解一下吧。01。微信视频放大我们在微信聊天时,别人发来视频,点击全屏播放……一带一路框架下对中哈吉户外体育旅游开发设想梁媛周军张峰摘要:本论文的研究在2017。5。3一带一路高峰论坛的召开背景下,相应2016年10。25国发院发布的国办发〔2016〕77号文件,对于指导我国体育产业尤其是……对我国立体商标显著性认定分析与建议摘要:立体商标也叫做三维商标。与以往的平面商标不同,立体商标主要是采用立体标志、商品正外型或者实体包装物等立体形象。商品立体商标的选定必须真是反映商品的质量特点,并且具有一定的……越来越多的人选择生二胎,但是二胎妈妈的感受,又有谁体会过?越来越多的人选择生二胎,但是二胎妈妈的感受,又有谁体会过?我们都知道现在计划生育已经没有以前那么严格,越来越大的家庭,他们都希望能够生二胎,这样等自己老了以后自己的孩子还……现代诗向秋天告别飘零的叶子黄了、落了在每一个小巷沉默行人的脚步匆忙,踩出丰收的声音向秋天告别雀儿飞的身姿慢了留恋的眼神里映出别致的景……关于手机你知道多少第一部商用手提电话1973年,摩托罗拉公司推出了DynaTAC8000x,这是第一部商用手提电话,售价为近4000美元DynaTAC8000x第一部商用移动电……狐假虎威续写自从老虎被狐狸骗了以后,老虎心里一直非常恼火,暗暗下决心一定要报复狐狸。于是,老虎就来到了狐狸的家门口,对狐狸说:你这只狡猾的狐狸,上一次被你骗了,害我在百兽面前丢尽了脸……
鸿蒙系统3。0即将问世,分享8个华为手机隐藏功能,几千块钱没用了这么久华为手机,我最近才知道原来它有这么多隐藏功能,今天就给大家分享8个华为手机使用小技巧,看完绝对让你惊喜满满!1应用分身好多人的微信和QQ账号都不止一个,有时候切……你会挑选打底衫吗?3条技巧买到百搭好看的基础款打底衫关于打底衫这件基本单品的挑选与穿搭攻略,真的是每个女人穿好衣服、提升衣品必须学好的基本技能。今天,会买的妞来与大家分享一下我自己总结的几点挑选打底衫的实用技巧,仅大家交流和参考……在横店拍戏场地,为何明星不住酒店,而是住在自己的房车里?这是因为酒店是通床辅,没有了具体人的个性设置,没有了绝对的私人收藏空间,去酒店还得寻找车的停靠位;房车则有自己的精心设计空间,有了适应自身环境习惯的临时家。一个房车的空间是12……白鹿身材真的太棒了!一身抹胸公主裙将身材完美展现,太心动了白鹿人如其名有着一双像小鹿一般灵动的眼眸,她的皮肤白皙,身材姣好,是新生代小花里炙手可热的存在。白鹿最先是做网红,她经常去给书拍封面,做起了书模,在之后她就受邀为猫的树拍……一枪爆头回到30年前,开挂首赚240亿重生爽文被韩国拍成爆款大家对韩剧的印象是什么?还是帅哥、靓女,癌症、车祸和失忆的爱情故事吗?!现在的韩剧已经从20年前只会讲述浪漫爱情故事的工业糖精甜甜圈,转变为映射政治与阶级、刻画社会各阶层人民生……八维智能工程专业有哪些应用领域?随着智能技术在现实生活中的广泛应用,人们越来越感受到智能产品为生活带来的便利,智能工程技术的出现更为人们享受生活提供了一个广阔的平台。智能工程技术的出现让我们更好的管理、……网曝陈梦比刘诗雯更早退役!指出退役的3大理由,球迷完全同意12月27日,距离2021赛季结束仅剩4天时间,网上突然传出陈梦或将比刘诗雯更早退役的消息,并且指出陈梦比刘诗雯更早退役的3大理由,引发网友、球迷的激烈讨论。关注国乒的球迷应该……重建计划中的最大谜团!美记休斯顿火箭选秀瞄准切特霍姆格伦随着火箭主场114比130不敌老鹰,休城人确定以全联盟倒数第一的战绩结束了本赛季的征程。在赛季落幕战中,榜眼秀杰伦格林把自己近来的演出推向了新的高潮。他登场40分钟狂轰生……身上有这几种表现,表明你体内湿气很重了曹先生,四十岁左右,最近患上了湿疹,买了药擦身子,但是都没有得到缓解,还越来越多,情况也越来越严重。于是他就想到找中医调理一下,就找到我了。在面诊过程中了解到,这位患者除……铁子完了,中国足球的春天到了吗?四年一度的足球盛事终于落下帷幕,梅球王终于正式加冕,足球真的值得!大家有没有发现:足球场周围电子屏频繁出现的中国企业广告?这些广告是不是都是中文的?没错,这都是给咱们国人……广东赢球后!杜锋调侃阿联为小易,00后徐杰成老将,4大01后CBA常规赛第18轮,广东宏远124103战胜福建男篮,赛后,主教练杜锋和阿联出席新闻发布会,杜锋总结本场比赛的时候说道:祝贺我们‘小将’易建联同学获得了人生当中的常规赛一万分……治疗前列腺增生,中医有哪些方法?今日主题:中医如何分析前列腺增生的发病原因?中医认为,前列腺增生属于中医的癃闭范畴。《黄帝内经》《灵枢本输》:三焦者实则闭癃,虚则遗溺,遗溺则补之,闭癃则泻之。三焦,主要是指人……
友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找