幼儿饰品瑜伽美体用品微软
投稿投诉
微软创意
爱情通信
用品婚姻
爱好看病
美体软件
影音星座
瑜伽周边
星座办公
饰品塑形
搞笑减肥
幼儿两性
智家潮品

面试官你说说限流的原理?

  限流作为现在微服务中常见的稳定性措施,在面试中肯定也是经常会被问到的,我在面试的时候也经常喜欢问一下你对限流算法知道哪一些?有看过源码吗?实现原理是什么?
  第一部分先讲讲限流算法,最后再讲讲源码的实现原理。限流算法
  关于限流的算法大体上可以分为四类:固定窗口计数器、滑动窗口计数器、漏桶(也有称漏斗,英文Leakybucket)、令牌桶(英文Tokenbucket)。固定窗口
  固定窗口,相比其他的限流算法,这应该是最简单的一种。
  它简单地对一个固定的时间窗口内的请求数量进行计数,如果超过请求数量的阈值,将被直接丢弃。
  这个简单的限流算法优缺点都很明显。优点的话就是简单,缺点举个例子来说。
  比如我们下图中的黄色区域就是固定时间窗口,默认时间范围是60s,限流数量是100。
  如图中括号内所示,前面一段时间都没有流量,刚好后面30秒内来了100个请求,此时因为没有超过限流阈值,所以请求全部通过,然后下一个窗口的20秒内同样通过了100个请求。
  所以变相的相当于在这个括号的40秒的时间内就通过了200个请求,超过了我们限流的阈值。
  滑动窗口
  为了优化这个问题,于是有了滑动窗口算法,顾名思义,滑动窗口就是时间窗口在随着时间推移不停地移动。
  滑动窗口把一个固定时间窗口再继续拆分成N个小窗口,然后对每个小窗口分别进行计数,所有小窗口请求之和不能超过我们设定的限流阈值。
  以下图举例子来说,假设我们的窗口拆分成了3个小窗口,小窗口都是20s,同样基于上面的例子,当在第三个20s的时候来了100个请求,可以通过。
  然后时间窗口滑动,下一个20s请求又来了100个请求,此时我们滑动窗口的60s范围内请求数量肯定就超过100了啊,所以请求被拒绝。
  漏桶Leakybucket
  漏桶算法,人如其名,他就是一个漏的桶,不管请求的数量有多少,最终都会以固定的出口流量大小匀速流出,如果请求的流量超过漏桶大小,那么超出的流量将会被丢弃。
  也就是说流量流入的速度是不定的,但是流出的速度是恒定的。
  这个和MQ削峰填谷的思想比较类似,在面对突然激增的流量的时候,通过漏桶算法可以做到匀速排队,固定速度限流。
  漏桶算法的优势是匀速,匀速是优点也是缺点,很多人说漏桶不能处理突增流量,这个说法并不准确。
  漏桶本来就应该是为了处理间歇性的突增流量,流量一下起来了,然后系统处理不过来,可以在空闲的时候去处理,防止了突增流量导致系统崩溃,保护了系统的稳定性。
  但是,换一个思路来想,其实这些突增的流量对于系统来说完全没有压力,你还在慢慢地匀速排队,其实是对系统性能的浪费。
  所以,对于这种有场景来说,令牌桶算法比漏桶就更有优势。令牌桶tokenbucket
  令牌桶算法是指系统以一定地速度往令牌桶里丢令牌,当一个请求过来的时候,会去令牌桶里申请一个令牌,如果能够获取到令牌,那么请求就可以正常进行,反之被丢弃。
  现在的令牌桶算法,像Guava和Sentinel的实现都有冷启动预热的方式,为了避免在流量激增的同时把系统打挂,令牌桶算法会在最开始一段时间内冷启动,随着流量的增加,系统会根据流量大小动态地调整生成令牌的速度,最终直到请求达到系统的阈值。源码举例
  我们以sentinel举例,sentinel中统计用到了滑动窗口算法,然后也有用到漏桶、令牌桶算法。滑动窗口
  sentinel中就使用到了滑动窗口算法来进行统计,不过他的实现和我上面画的图有点不一样,实际上sentinel中的滑动窗口用一个圆形来描述更合理一点。
  前期就是创建节点,然后slot串起来就是一个责任链模式,StatisticSlot通过滑动窗口来统计数据,FlowSlot是真正限流的逻辑,还有一些降级、系统保护的措施,最终形成了整个sentinel的限流方式。
  滑动窗口的实现主要可以看LeapArray的代码,默认的话定义了时间窗口的相关参数。
  对于sentinel来说其实窗口分为秒和分钟两个级别,秒的话窗口数量是2,分钟则是60个窗口,每个窗口的时间长度是1s,总的时间周期就是60s,分成60个窗口,这里我们就以分钟级别的统计来说。publicabstractclassLeapArrayT{窗口时间长度,毫秒数,默认1000msprotectedintwindowLengthInMs;窗口数量,默认60protectedintsampleCount;毫秒时间周期,默认601000protectedintintervalInMs;秒级时间周期,默认60privatedoubleintervalInSecond;时间窗口数组protectedfinalAtomicReferenceArrayWindowWrapTarray;
  然后我们要看的就是它是怎么计算出当前窗口的,其实源码里写的听清楚的,但是如果你按照之前想象把他当做一条直线延伸去想的话估计不太好理解。
  首先计算数组索引下标和时间窗口时间这个都比较简单,难点应该大部分在于第三点窗口大于old这个是什么鬼,详细说下这几种情况。数组中的时间窗口是是空的,这个说明时间走到了我们初始化的时间之后了,此时new一个新的窗口通过CAS的方式去更新,然后返回这个新的窗口就好了。第二种情况是刚好时间窗口的时间相等,那么直接返回,没啥好说的第三种情况就是比较难以理解的,可以参看两条时间线的图,就比较好理解了,第一次时间窗口走完了达到1200,然后圆形时间窗口开始循环,新的时间起始位置还是1200,然后时间窗口的时间来到1676,B2的位置如果还是老的窗口那么就是600,所以我们要重置之前的时间窗口的时间为当前的时间。最后一种一般情况不太可能发生,除非时钟回拨这样子
  从这个我们可以发现就是针对每个WindowWrap时间窗口都进行了统计,最后实际上在后面的几个地方都会用到时间窗口统计的QPS结果,这里就不再赘述了,知道即可。privateintcalculateTimeIdx(ValidlongtimeMillis){longtimeIdtimeMilliswindowLengthInMs;Calculatecurrentindexsowecanmapthetimestamptotheleaparray。return(int)(timeIdarray。length());}protectedlongcalculateWindowStart(ValidlongtimeMillis){returntimeMillistimeMilliswindowLengthInMs;}publicWindowWrapTcurrentWindow(longtimeMillis){当前时间如果小于0,返回空if(timeMillis0){returnnull;}计算时间窗口的索引intidxcalculateTimeIdx(timeMillis);计算当前时间窗口的开始时间longwindowStartcalculateWindowStart(timeMillis);while(true){在窗口数组中获得窗口WindowWrapToldarray。get(idx);if(oldnull){B0B1B2NULLB420040060080010001200timestamptime888比如当前时间是888,根据计算得到的数组窗口位置是个空,所以直接创建一个新窗口就好了WindowWrapTwindownewWindowWrapT(windowLengthInMs,windowStart,newEmptyBucket(timeMillis));if(array。compareAndSet(idx,null,window)){Successfullyupdated,returnthecreatedbucket。returnwindow;}else{Contentionfailed,thethreadwillyielditstimeslicetowaitforbucketavailable。Thread。yield();}}elseif(windowStartold。windowStart()){B0B1B2B3B420040060080010001200timestamptime888这个更好了,刚好等于,直接返回就行returnold;}elseif(windowStartold。windowStart()){B0B1B2B3B420040060080010001200timestampB0B1B2NULLB4。。。120014001600180020002200timestamptime1676这个要当成圆形理解就好了,之前如果是1200一个完整的圆形,然后继续从1200开始,如果现在时间是1676,落在在B2的位置,窗口开始时间是1600,获取到的old时间其实会是600,所以肯定是过期了,直接重置窗口就可以了if(updateLock。tryLock()){try{Successfullygettheupdatelock,nowweresetthebucket。returnresetWindowTo(old,windowStart);}finally{updateLock。unlock();}}else{Thread。yield();}}elseif(windowStartold。windowStart()){这个不太可能出现,嗯时钟回拨returnnewWindowWrapT(windowLengthInMs,windowStart,newEmptyBucket(timeMillis));}}}漏桶
  sentinel主要根据FlowSlot中的流控进行流量控制,其中RateLimiterController就是漏桶算法的实现,这个实现相比其他几个还是简单多了,稍微看一下应该就明白了。首先计算出当前请求平摊到1s内的时间花费,然后去计算这一次请求预计时间如果小于当前时间的话,那么以当前时间为主,返回即可反之如果超过当前时间的话,这时候就要进行排队等待了,等待的时候要判断是否超过当前最大的等待时间,超过就直接丢弃没有超过就更新上一次的通过时间,然后再比较一次是否超时,还超时就重置时间,反之在等待时间范围之内的话就等待,如果都不是那就可以通过了publicclassRateLimiterControllerimplementsTrafficShapingController{最大等待超时时间,默认500msprivatefinalintmaxQueueingTimeMs;限流数量privatefinaldoublecount;上一次的通过时间privatefinalAtomicLonglatestPassedTimenewAtomicLong(1);OverridepublicbooleancanPass(Nodenode,intacquireCount,booleanprioritized){Passwhenacquirecountislessorequalthan0。if(acquireCount0){returntrue;}Rejectwhencountislessorequalthan0。Otherwise,thecostTimewillbemaxoflongandwaitTimewilloverflowinsomecases。if(count0){returnfalse;}longcurrentTimeTimeUtil。currentTimeMillis();时间平摊到1s内的花费longcostTimeMath。round(1。0(acquireCount)count1000);1100100010ms计算这一次请求预计的时间longexpectedTimecostTimelatestPassedTime。get();花费时间小于当前时间,pass,最后通过时间当前时间if(expectedTimecurrentTime){latestPassedTime。set(currentTime);returntrue;}else{预计通过的时间超过当前时间,要进行排队等待,重新获取一下,避免出现问题,差额就是需要等待的时间longwaitTimecostTimelatestPassedTime。get()TimeUtil。currentTimeMillis();等待时间超过最大等待时间,丢弃if(waitTimemaxQueueingTimeMs){returnfalse;}else{反之,可以更新最后一次通过时间了longoldTimelatestPassedTime。addAndGet(costTime);try{waitTimeoldTimeTimeUtil。currentTimeMillis();更新后再判断,还是超过最大超时时间,那么就丢弃,时间重置if(waitTimemaxQueueingTimeMs){latestPassedTime。addAndGet(costTime);returnfalse;}在时间范围之内的话,就等待if(waitTime0){Thread。sleep(waitTime);}returntrue;}catch(InterruptedExceptione){}}}returnfalse;}}令牌桶
  最后是令牌桶,这个不在于实现的复制,而是你看源码会发现都算的些啥玩意儿sentinel的令牌桶实现基于Guava,代码在WarmUpController中。
  这个算法那些各种计算逻辑其实我们可以不管(因为我也没看懂),但是流程上我们是清晰的就可以了。
  几个核心的参数看注释,构造方法里那些计算逻辑暂时不管他是怎么算的(我也没整明白,但是不影响我们理解),关键看canPass是怎么做的。拿到当前窗口和上一个窗口的QPS填充令牌,也就是往桶里丢令牌,然后我们先看填充令牌的逻辑publicclassWarmUpControllerimplementsTrafficShapingController{限流QPSprotecteddoublecount;冷启动系数,默认3privateintcoldFactor;警戒的令牌数protectedintwarningToken0;最大令牌数privateintmaxToken;斜率,产生令牌的速度protecteddoubleslope;存储的令牌数量protectedAtomicLongstoredTokensnewAtomicLong(0);最后一次填充令牌时间protectedAtomicLonglastFilledTimenewAtomicLong(0);publicWarmUpController(doublecount,intwarmUpPeriodInSec,intcoldFactor){construct(count,warmUpPeriodInSec,coldFactor);}publicWarmUpController(doublecount,intwarmUpPeriodInSec){construct(count,warmUpPeriodInSec,3);}privatevoidconstruct(doublecount,intwarmUpPeriodInSec,intcoldFactor){if(coldFactor1){thrownewIllegalArgumentException(Coldfactorshouldbelargerthan1);}this。countcount;this。coldFactorcoldFactor;stableInterval稳定产生令牌的时间周期,1QPSwarmUpPeriodInSec预热冷启动时间,默认10swarningToken(int)(warmUpPeriodInSeccount)(coldFactor1);maxTokenwarningToken(int)(2warmUpPeriodInSeccount(1。0coldFactor));斜率的计算参考Guava,当做一个固定改的公式slope(coldFactor1。0)count(maxTokenwarningToken);}OverridepublicbooleancanPass(Nodenode,intacquireCount,booleanprioritized){当前时间窗口通过的QPSlongpassQps(long)node。passQps();上一个时间窗口QPSlongpreviousQps(long)node。previousPassQps();填充令牌syncToken(previousQps);开始计算它的斜率如果进入了警戒线,开始调整他的qpslongrestTokenstoredTokens。get();if(restTokenwarningToken){当前的令牌超过警戒线,获得超过警戒线的令牌数longaboveTokenrestTokenwarningToken;消耗的速度要比warning快,但是要比慢currentintervalrestTokenslope1countdoublewarningQpsMath。nextUp(1。0(aboveTokenslope1。0count));if(passQpsacquireCountwarningQps){returntrue;}}else{if(passQpsacquireCountcount){returntrue;}}returnfalse;}}
  填充令牌的逻辑如下:拿到当前的时间,然后去掉毫秒数,得到的就是秒级时间判断时间小于这里就是为了控制每秒丢一次令牌然后就是coolDownTokens去计算我们的冷启动预热是怎么计算填充令牌的后面计算当前剩下的令牌数这个就不说了,减去上一次消耗的就是桶里剩下的令牌protectedvoidsyncToken(longpassQps){longcurrentTimeTimeUtil。currentTimeMillis();去掉当前时间的毫秒currentTimecurrentTimecurrentTime1000;longoldLastFillTimelastFilledTime。get();控制每秒填充一次令牌if(currentTimeoldLastFillTime){return;}当前的令牌数量longoldValuestoredTokens。get();获取新的令牌数量,包含添加令牌的逻辑,这就是预热的逻辑longnewValuecoolDownTokens(currentTime,passQps);if(storedTokens。compareAndSet(oldValue,newValue)){存储的令牌数量当然要减去上一次消耗的令牌longcurrentValuestoredTokens。addAndGet(0passQps);if(currentValue0){storedTokens。set(0L);}lastFilledTime。set(currentTime);}}最开始的事实因为lastFilledTime和oldValue都是0,所以根据当前时间戳会得到一个非常大的数字,最后和maxToken取小的话就得到了最大的令牌数,所以第一次初始化的时候就会生成maxToken的令牌之后我们假设系统的QPS一开始很低,然后突然飙高。所以开始的时候回一直走到高于警戒线的逻辑里去,然后passQps又很低,所以会一直处于把令牌桶填满的状态(currentTimelastFilledTime。get()会一直都是1000,也就是1秒),所以每次都会填充最大QPScount数量的令牌然后突增流量来了,QPS瞬间很高,慢慢地令牌数量就会消耗到警戒线之下,走到我们if的逻辑里去,然后去按照count数量增加令牌privatelongcoolDownTokens(longcurrentTime,longpassQps){longoldValuestoredTokens。get();longnewValueoldValue;水位低于警戒线,就生成令牌if(oldValuewarningToken){如果桶中令牌低于警戒线,根据上一次的时间差,得到新的令牌数,因为去掉了毫秒,1秒生成的令牌就是阈值count第一次都是0的话,会生成count数量的令牌newValue(long)(oldValue(currentTimelastFilledTime。get())count1000);}elseif(oldValuewarningToken){反之,如果是高于警戒线,要判断QPS。因为QPS越高,生成令牌就要越慢,QPS低的话生成令牌要越快if(passQps(int)countcoldFactor){newValue(long)(oldValue(currentTimelastFilledTime。get())count1000);}}不要超过最大令牌数returnMath。min(newValue,maxToken);}
  上面的逻辑理顺之后,我们就可以继续看限流的部分逻辑:令牌计算的逻辑完成,然后判断是不是超过警戒线,按照上面的说法,低QPS的状态肯定是一直超过的,所以会根据斜率来计算出一个warningQps,因为我们处于冷启动的状态,所以这个阶段就是要根据斜率来计算出一个QPS数量,让流量慢慢地达到系统能承受的峰值。举个例子,如果count是100,那么在QPS很低的情况下,令牌桶一直处于满状态,但是系统会控制QPS,实际通过的QPS就是warningQps,根据算法可能只有10或者20(怎么算的不影响理解)。QPS主键提高的时候,aboveToken再逐渐变小,整个warningQps就在逐渐变大,直到走到警戒线之下,到了else逻辑里。流量突增的情况,就是else逻辑里低于警戒线的情况,我们令牌桶在不停地根据count去增加令牌,这时候消耗令牌的速度超过我们生成令牌的速度,可能就会导致一直处于警戒线之下,这时候判断当然就需要根据最高QPS去判断限流了。longrestTokenstoredTokens。get();if(restTokenwarningToken){当前的令牌超过警戒线,获得超过警戒线的令牌数longaboveTokenrestTokenwarningToken;消耗的速度要比warning快,但是要比慢currentintervalrestTokenslope1countdoublewarningQpsMath。nextUp(1。0(aboveTokenslope1。0count));if(passQpsacquireCountwarningQps){returntrue;}}else{if(passQpsacquireCountcount){returntrue;}}
  所以,按照低QPS到突增高QPS的流程,来想象一下这个过程:刚开始,系统的QPS非常低,初始化我们就直接把令牌桶塞满了然后这个低QPS的状态持续了一段时间,因为我们一直会填充最大QPS数量的令牌(因为取最小值,所以其实桶里令牌基本不会有变化),所以令牌桶一直处于满的状态,整个系统的限流也处于一个比较低的水平
  这以上的部分一直处于警戒线之上,实际上就是叫做冷启动预热的过程。接着系统的QPS突然激增,令牌消耗速度太快,就算我们每次增加最大QPS数量的令牌任然无法维持消耗,所以桶里的令牌在不断低减少,这个时候,冷启动阶段的限制QPS也在不断地提高,最后直到桶里的令牌低于警戒线低于警戒线之后,系统就会按照最高QPS去限流,这个过程就是系统在逐渐达到最高限流的过程
  那这样一来,实际就达到了我们处理突增流量的目的,整个系统在漫漫地适应突然飙高的QPS,然后最终达到系统的QPS阈值。最后,如果QPS回复正常,那么又会逐渐回到警戒线之上,就回到了最开始的过程。
  总结
  因为算法如果单独说的话都比较简单,一说大家都可以听明白,不需要几个字就能说明白,所以还是得弄点源码看看别人是怎么玩的,所以尽管我很讨厌放源码,但是还是不得不干。
  光靠别人说一点其实有点看不明白,按照顺序读一遍的话心里就有数了。
  那源码的话最难以理解的就是令牌桶的实现了,说实话那几个计算的逻辑我看了好几遍不知道他算的什么鬼,但是思想我们理解就行了,其他的逻辑相对来说就比较容易理解。

三叉戟,这老三位让我觉得警察团队除了严谨外还挺可爱的不谈立意崇高与否,不提与现实相差多远,这个剧本身,是让我挺感动的。所谓老骥伏枥宝刀未老,说的就是这部剧里即将退休的几位。有三叉戟的老三位,有楚呱嗒楚政委,还有老郭郭局长。……她是香港腿精,腿长超1米,未成年就被众多富二代盯上?有一位香港腿精,她叫任晴佳。父亲是任达华,母亲叫琦琦,而任晴佳遗传了父母的演绎细胞,有一次那是任晴佳三岁,和妈妈逛街的时候突然想要走秀,于是在大街上就秀起来,充满了表演欲……曾红过王菲那英,却不顾父母反对嫁大37岁老公,离婚至今单身提到祖海这个名字不知道你熟不熟悉,曾经的她要比那英和王菲还要红火,但就是如此优秀的她最终却嫁给了一位比自己大37岁的老男人,在我们看来这是非常不可思议的事情,可能像他们这样的艺……特斯拉如果退出中国谁的损失更大新能源汽车4月销售数据出炉,五菱宏光MINI依然高居榜首,紧随其后的也还是特斯拉,但相较3月的数据,特斯拉有大幅减少。与排名第三的比亚迪差距已明显缩小。特斯拉过山车式的销……上海月薪一万真的不够用,每个月都要节衣缩食五年之前月薪3000元刚刚来上海的时候,那时候是3000块钱一个月,每个月租房都要1500,每个都是负的,也不知道那个时候哪里来的勇气在上海坚持了五年。那个时候我还……格莱美风波唱片学院首席执行官在格莱美颁奖礼前一周被撤职唱片学院首席执行官DeborahDugan黛博拉杜根去年8月接替尼尔波特诺(NeilPortnow)担任美国唱片学院(RecordingAcademy)院长兼首席执行官的……长津湖真的有续集?豆瓣已有词条,时长两小时剑指春节档今年国庆档最火爆的电影无疑是抗美援朝电影《长津湖》,截至影片上映第6天晚间20点左右,电影累计票房已破24亿元,而同期上映的《我和我的父辈》,累计票房只有8亿多,足以看出前者的……涅槃乐队被起诉!30年前专辑封面被控对儿童性剥削据外媒报道,涅槃乐队1991年发行的专辑《Nevermind》封面上的裸体婴儿本人起诉乐队对儿童性剥削。一位名叫斯宾塞埃尔登(SpencerElden)的男子声称,他就是……顶替陈数出演集结号女主,14年过去,她依旧没红起来2006年,著名导演冯小刚集结张涵予、邓超、袁文康、廖凡、王宝强等实力派演员,拍摄了影片《集结号》,经过数月的拍摄,该片最终于2007年12月20日在中国内地上映,并迅速取得强……朗朗娇妻吉娜晒视频,穿传统戏服袋鼠摇手,头戴4毛钱夹子接地气近日,著名音乐家朗朗的老婆吉娜在本人社交网络平台公布了一则视频,视频中的吉娜衣着传统式戏服,演出近期受欢迎各大网站的澳洲袋鼠摆手。界面中,吉娜身穿传统式戏服,宽敞的戏服将……马思纯发福被嘲讽,阚清子被经纪人逼减肥,女明星为什么要瘦?近日,马思纯现身最新一期《脱口秀大会》,不过不是在台上,而是在台下。作为脱口秀的迷妹,马思纯以观众的身份到场支持。台下坐着一个金像奖影后,李诞怎能放过这样大好的机会,于是……实际分析一下目前最火的哈弗H6的优点及不足哈弗h6外观大气,成熟稳重,目前在售的第三代哈弗h6前脸算是一个亮点,车头采用了类似梯形的大面积格栅式镀铬中网,立体感很强,极具辨识度;前包围采用了与中网平行镂空的设计,气场强……
水落石出!林生斌事件终于告一段落,官方发布通告回应网络质疑近段时间,网络上曝出的最大的两个瓜,一个是林生斌事件的反转,一个是吴亦凡的翻车,可谓是让吃瓜群众过足了瓜瘾,在吴亦凡锒铛入狱之后,林生斌事件官方的最新通告也终于发出。8月……双眼皮大眼睛已经过时了,现在的美女标准是这样有姑娘问我:变美到底有没有捷径?当然是有的!今年大家经常说起一个词,明星味,就是最好的答案:即使不是双眼皮、大眼睛,但明星味儿足了,气质颜值马上蹭蹭上涨!别小……比起睡你,我更想好好爱你。这几天在看《摩天大楼》的时候,看到这样一个情节:林梦宇和丁小玲是一对情人。他们经常约在一起上床,发生亲密关系。他们的关系,委婉一些说是情人,直白一些说其实是炮……两会期间,少儿编程再获全民关注育总是需要随着时代的发展不断革新的。近年来,新的学习工具,学习方式、学习领域层出不穷,这些新兴事物的诞生和发展,也催动着教育加速变革和创新。现在大家所关心的莫过于两会的召……锦衣后谭松韵又一新剧引关注!角色造型犀利,演员阵容强大(相对电影社原创发布:敬请关注)去年底至今年初,曾有一部颇为奇特剧集,在刚开播时,便因五毛特效及劣质抠图,引发吐槽声无数。但之后随着剧情深入,以及男女主角浑然天成的高甜C……陈陈陈称父亲的爱是还不清的债,单亲家庭对孩子的影响远超你想象在最新一期《五十公里桃花坞》中,苏芒、郭麒麟、李雪华等人热心为陈陈陈庆祝生日,本来气氛很好很融洽,却不料陈陈陈突然想起自己成长过程中的一些往事,忍不住伤心落泪,气氛一下子变是凝……民间故事寡妇池塘洗澡,渔夫忙朝水里撒泡尿,因此得一桩好姻缘万寡妇乃唐朝扬州人氏,她刚成婚那年便守了寡,虽三十多岁了,却依旧风姿绰约,美貌依旧。很多人看上了万寡妇的美貌,向她提亲的人络绎不绝,万寡妇似乎没有改嫁的打算,她通通拒绝了。……范冰冰又嫩了一把,针织套装身材臃肿,穿出街头大妈的感觉明星时尚穿搭可谓绚烂多姿,正式场合造型夸张、色彩艳丽,或雍容典雅,或大气成熟,美不胜收,但是她们的私服照却呈现另一番景象,摆脱舞台正式感,衣着更接地气,让粉丝们领略到她们日常穿……陆勇我不是药神的原型,当年为救人卖药被捕,如今怎么样了大家还记得18年那部非常火爆的电影《我不是药神》吗?虽然剧中的人物都很普通,但他们却成功地让所有走进影院的观众红了眼眶。世界上最感动的作品就是改编自真人真事,《我不是药神》就是……人美心善的何琳为照顾4位老人息影,成婆婆最大的骄傲何琳的人生,不管是事业还是家庭,从未有多风浪,在娱乐圈很少有人如她一样幸福。童星出道,早早的就拿下了国际影后的头衔。何琳一路走来兢兢业业,她的颜值和演技都受到了大家……跳水女皇吴敏霞官宣怀二胎喜讯,一家四口看北京冬奥会?8月6日,跳水女皇吴敏霞在社交平台晒出一张全家福,并配文:报数:1、2、3。。。。。。4!北京冬奥会就是一家四口看啦!官宣怀二胎喜讯。照片中,吴敏霞身穿白色T恤搭配宽松休……继罗志祥和妈妈亲吻后,李嘉欣被1米6的儿子摸胸,谈缺失的性教距离李嘉欣的巅峰时期已经过去了20年,但她依然是不少人心目中的不老女神。想当年,她在港姐选秀上一举夺冠,港媒只用了石破天惊这个成语来形容她的美丽。或许,就是因为她的……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网