专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

RocketMQ主从模式下的消费进度管理

  from:cnblogs。comshanmlp16989785。htm
  消费者在启动的时候,会创建消息拉取API对象PullAPIWrapper,调用pullKernelImpl方法向Broker发送拉取消息的请求,那么在主从模式下消费者是如何选择向哪个Broker发送拉取请求的?
  进入pullKernelImpl方法中,可以看到会调用recalculatePullFromWhichNode方法选择一个Broker:publicclassPullAPIWrapper{publicPullResultpullKernelImpl(finalMessageQueuemq,finalStringsubExpression,finalStringexpressionType,finallongsubVersion,finallongoffset,finalintmaxNums,finalintsysFlag,finallongcommitOffset,finallongbrokerSuspendMaxTimeMillis,finallongtimeoutMillis,finalCommunicationModecommunicationMode,finalPullCallbackpullCallback)throwsMQClientException,RemotingException,MQBrokerException,InterruptedException{调用recalculatePullFromWhichNode方法获取BrokerID,再调用findBrokerAddressInSubscribe根据ID获取Broker的相关信息FindBrokerResultfindBrokerResultthis。mQClientFactory。findBrokerAddressInSubscribe(mq。getBrokerName(),this。recalculatePullFromWhichNode(mq),false);。。。if(findBrokerResult!null){。。。获取Broker地址StringbrokerAddrfindBrokerResult。getBrokerAddr();if(PullSysFlag。hasClassFilterFlag(sysFlagInner)){brokerAddrcomputePullFromWhichFilterServer(mq。getTopic(),brokerAddr);}发送消息拉取请求PullResultpullResultthis。mQClientFactory。getMQClientAPIImpl()。pullMessage(brokerAddr,requestHeader,timeoutMillis,communicationMode,pullCallback);returnpullResult;}}}
  在recalculatePullFromWhichNode方法中,会从pullFromWhichNodeTable中根据消息队列获取一个建议的BrokerID,如果获取为空就返回Master节点的BrokerID,ROCKETMQ中Master角色的BrokerID为0,既然从pullFromWhichNodeTable中可以知道从哪个Broker拉取数据,那么pullFromWhichNodeTable中的数据又是从哪里来的?publicclassPullAPIWrapper{KEY为消息队列,VALUE为建议的BrokerIDprivateConcurrentMapMessageQueue,AtomicLongbrokerIdpullFromWhichNodeTablenewConcurrentHashMapMessageQueue,AtomicLong(32);publiclongrecalculatePullFromWhichNode(finalMessageQueuemq){if(this。isConnectBrokerByUser()){returnthis。defaultBrokerId;}从pullFromWhichNodeTable中获取建议的brokerIDAtomicLongsuggestthis。pullFromWhichNodeTable。get(mq);if(suggest!null){returnsuggest。get();}返回MasterBrokerIDreturnMixAll。MASTERID;}}
  通过调用关系可知,在updatePullFromWhichNode方法中更新了pullFromWhichNodeTable的值,而updatePullFromWhichNode方法又是被processPullResult方法调用的,消费者向Broker发送拉取消息请求后,Broker对拉取请求进行处理时会设置一个brokerID(后面会讲到),建议下次从这个Broker拉取消息,
  消费者对拉取请求返回的响应数据进行处理时会调用processPullResult方法,在这里将建议的BrokerID取出,调用updatePullFromWhichNode方法将其加入到了pullFromWhichNodeTable中:publicclassPullAPIWrapper{privateConcurrentMapMessageQueue,AtomicLongbrokerIdpullFromWhichNodeTablenewConcurrentHashMapMessageQueue,AtomicLong(32);publicPullResultprocessPullResult(finalMessageQueuemq,finalPullResultpullResult,finalSubscriptionDatasubscriptionData){PullResultExtpullResultExt(PullResultExt)pullResult;将拉取消息请求返回的建议BrokerID,加入到pullFromWhichNodeTable中this。updatePullFromWhichNode(mq,pullResultExt。getSuggestWhichBrokerId());。。。}publicvoidupdatePullFromWhichNode(finalMessageQueuemq,finallongbrokerId){AtomicLongsuggestthis。pullFromWhichNodeTable。get(mq);if(nullsuggest){向pullFromWhichNodeTable中添加数据this。pullFromWhichNodeTable。put(mq,newAtomicLong(brokerId));}else{suggest。set(brokerId);}}}
  接下来去看下是根据什么条件决定选择哪个Broker的。返回建议的BrokerID
  Broker在处理消费者拉取请求时,会调用PullMessageProcessor的processRequest方法,首先会调用MessageStore的getMessage方法获取消息内容,在返回的结果GetMessageResult中设置了一个是否建议从Slave节点拉取的属性(这个值的设置稍后再说),会根据是否建议从slave节点进行以下处理:如果建议从slave节点拉取消息,会调用subscriptionGroupConfig订阅分组配置的getWhichBrokerWhenConsumeSlowly方法获取从节点将ID设置到响应中,否则下次依旧建议从主节点拉取消息,将MASTER节点的ID设置到响应中;判断当前Broker的角色,如果是slave节点,并且配置了不允许从slave节点读取数据(SlaveReadEnablefalse),此时依旧建议从主节点拉取消息,将MASTER节点的ID设置到响应中;如果开启了允许从slave节点读取数据(SlaveReadEnabletrue),有以下两种情况:如果建议从slave节点拉消息,从订阅分组配置中获取从节点的ID,将ID设置到响应中;如果不建议从slave节点拉取消息,从订阅分组配置中获取设置的BrokerId;
  当然,如果未开启允许从Slave节点读取数据,下次依旧建议从Master节点拉取;
  订阅分组配置
  mqadmin命令的i参数可以指定从哪个Broker消费消息(subscriptionGroupConfig的getBrokerId返回的值),w参数可以指定建议从slave节点消费的时候,从哪个slave消费(subscriptionGroupConfig的getWhichBrokerWhenConsumeSlowly方法返回的值):usage:mqadminupdateSubGroup〔a〕〔b〕〔c〕〔d〕g〔h〕〔i〕〔m〕〔n〕〔q〕〔r〕〔s〕〔w〕i,brokerIdconsumerfromwhichbrokeridw,whichBrokerWhenConsumeSlowlywhichbrokeridwhenconsumeslowlypublicclassPullMessageProcessorextendsAsyncNettyRequestProcessorimplementsNettyRequestProcessor{privateRemotingCommandprocessRequest(finalChannelchannel,RemotingCommandrequest,booleanbrokerAllowSuspend)throwsRemotingCommandException{。。。根据拉取偏移量获取消息finalGetMessageResultgetMessageResultthis。brokerController。getMessageStore()。getMessage(requestHeader。getConsumerGroup(),requestHeader。getTopic(),requestHeader。getQueueId(),requestHeader。getQueueOffset(),requestHeader。getMaxMsgNums(),messageFilter);if(getMessageResult!null){response。setRemark(getMessageResult。getStatus()。name());responseHeader。setNextBeginOffset(getMessageResult。getNextBeginOffset());responseHeader。setMinOffset(getMessageResult。getMinOffset());responseHeader。setMaxOffset(getMessageResult。getMaxOffset());是否建议从从节点拉取消息if(getMessageResult。isSuggestPullingFromSlave()){选择一个从节点responseHeader。setSuggestWhichBrokerId(subscriptionGroupConfig。getWhichBrokerWhenConsumeSlowly());}else{responseHeader。setSuggestWhichBrokerId(MixAll。MASTERID);}判断Broker的角色switch(this。brokerController。getMessageStoreConfig()。getBrokerRole()){caseASYNCMASTER:caseSYNCMASTER:break;caseSLAVE:如果不允许从从节点读取数据,设置为MasterIDif(!this。brokerController。getBrokerConfig()。isSlaveReadEnable()){response。setCode(ResponseCode。PULLRETRYIMMEDIATELY);responseHeader。setSuggestWhichBrokerId(MixAll。MASTERID);}break;}如果开启了允许从从节点读取数据if(this。brokerController。getBrokerConfig()。isSlaveReadEnable()){如果建议从从节点拉消息if(getMessageResult。isSuggestPullingFromSlave()){获取从节点responseHeader。setSuggestWhichBrokerId(subscriptionGroupConfig。getWhichBrokerWhenConsumeSlowly());}else{获取指定的brokerresponseHeader。setSuggestWhichBrokerId(subscriptionGroupConfig。getBrokerId());}}else{使用Master节点responseHeader。setSuggestWhichBrokerId(MixAll。MASTERID);}}else{response。setCode(ResponseCode。SYSTEMERROR);response。setRemark(storegetMessagereturnnull);}}}是否建议从Slave节点拉取的设置
  DefaultMessageStore的getMessage方法中用于获取消息内容,并会根据消费者的拉取进度判断是否建议下次从Slave节点拉取消息,判断过程如下:diff:当前CommitLog最大的偏移量减去本次拉取消息的最大物理偏移量,表示剩余未拉取的消息;memory:消息在PageCache中的总大小,计算方式是总物理内存消息存储在内存中的阀值(默认为40)100,也就是说MQ会缓存一部分消息在操作系统的PageCache中,加速访问;如果diff大于memory,表示未拉取的消息过多,已经超出了PageCache缓存的数据的大小,还需要从磁盘中获取消息,所以此时会建议下次从Slave节点拉取;publicclassDefaultMessageStoreimplementsMessageStore{publicGetMessageResultgetMessage(finalStringgroup,finalStringtopic,finalintqueueId,finallongoffset,finalintmaxMsgNums,finalMessageFiltermessageFilter){。。。当前CommitLog的最大偏移量finallongmaxOffsetPythis。commitLog。getMaxOffset();ConsumeQueueconsumeQueuefindConsumeQueue(topic,queueId);if(consumeQueue!null){minOffsetconsumeQueue。getMinOffsetInQueue();maxOffsetconsumeQueue。getMaxOffsetInQueue();if(maxOffset0){。。。}else{根据消费进度获取消息队列SelectMappedBufferResultbufferConsumeQueueconsumeQueue。getIndexBuffer(offset);if(bufferConsumeQueue!null){try{。。。CommitLog最大偏移量减去本次拉取消息的最大物理偏移量longdiffmaxOffsetPymaxPhyOffsetPulling;计算消息在PageCache中的总大小(总物理内存消息存储在内存中的阀值100)longmemory(long)(StoreUtil。TOTALPHYSICALMEMORYSIZE(this。messageStoreConfig。getAccessMessageInMemoryMaxRatio()100。0));是否建议下次去从节点拉取消息getResult。setSuggestPullingFromSlave(diffmemory);}finally{bufferConsumeQueue。release();}}else{。。。}}}else{statusGetMessageStatus。NOMATCHEDLOGICQUEUE;nextBeginOffsetnextOffsetCorrection(offset,0);}。。。returngetResult;}}
  总结
  消费者在启动后需要向Broker发送拉取消息的请求,Broker收到请求后会根据消息的拉取进度,返回一个建议的BrokerID,并设置到响应中返回,消费者处理响应时将建议的BrokerID放入pullFromWhichNodeTable,下次拉去消息的时候从pullFromWhichNodeTable中取出,并向其发送请求拉取消息。消费进度持久化
  上面讲解了主从模式下如何选择从哪个Broker拉取消息,接下来看下消费进度的持久化,因为广播模式下消费进度保存在每个消费者端,集群模式下消费进度保存在Broker端,所以接下来以集群模式为例。
  在【RocketMQ】消息的拉取一文中可知,集群模式下主要是通过RemoteBrokerOffsetStore进行消费进度管理的,在持久化方法persistAll中会调用updateConsumeOffsetToBroker更新Broker端的消费进度:publicclassRemoteBrokerOffsetStoreimplementsOffsetStore{OverridepublicvoidpersistAll(SetMessageQueuemqs){if(nullmqsmqs。isEmpty())return;finalHashSetMessageQueueunusedMQnewHashSetMessageQueue();for(Map。EntryMessageQueue,AtomicLongentry:this。offsetTable。entrySet()){MessageQueuemqentry。getKey();AtomicLongoffsetentry。getValue();if(offset!null){if(mqs。contains(mq)){try{向Broker发送请求更新消费进度this。updateConsumeOffsetToBroker(mq,offset。get());log。info(〔persistAll〕Group:{}ClientId:{}updateConsumeOffsetToBroker{}{},this。groupName,this。mQClientFactory。getClientId(),mq,offset。get());}catch(Exceptione){log。error(updateConsumeOffsetToBrokerexception,mq。toString(),e);}}else{unusedMQ。add(mq);}}}。。。}}
  由于updateConsumeOffsetToBroker方法中先调用了findBrokerAddressInSubscribe方法获取Broker的信息,所以这里先看findBrokerAddressInSubscribe方法是如何选择Broker的,它需要传入三个参数,分别为:Broker名称、BrokerID、是否只查找参数中传入的那个BrokerID,方法的处理逻辑如下:首先从brokerAddrTable中根据Broker的名称获取所有的Broker集合(主从模式下他们的Broker名称一致,但是ID不一致),KEY为BrokerID,VALUE为Broker的地址;从Broker集合中根据参数中传入的ID获取broker地址;判断参数中传入的BrokerID是否是主节点,记录在slave变量中;判断获取的Broker地址是否为空,记录在found变量中;如果根据BrokerId获取的地址为空并且参数中传入的BrokerId为从节点,继续轮询获取下一个Broker,并判断地址是否为空;如果此时地址依旧为空并且onlyThisBroker传入的false(也就是不必须选择参数中传入的那个BrokerID),此时获取map集合中的第一个节点;判断获取到的Broker地址是否为空,不为空封装结果返回,否则返回NULL;publicclassMQClientInstance{publicFindBrokerResultfindBrokerAddressInSubscribe(finalStringbrokerName,Broker名称finallongbrokerId,BrokerIDfinalbooleanonlyThisBroker是否只查找参数中传入的那个BrokerID){StringbrokerAddrnull;booleanslavefalse;booleanfoundfalse;获取所有的BrokerIDHashMapLongbrokerId,Stringaddressmapthis。brokerAddrTable。get(brokerName);if(map!null!map。isEmpty()){brokerAddrmap。get(brokerId);是否是从节点slavebrokerId!MixAll。MASTERID;地址是否为空foundbrokerAddr!null;如果地址为空并且是从节点if(!foundslave){获取下一个BrokerbrokerAddrmap。get(brokerId1);foundbrokerAddr!null;}如果地址为空if(!found!onlyThisBroker){获取集合中的第一个节点EntryLong,Stringentrymap。entrySet()。iterator()。next();获取地址brokerAddrentry。getValue();是否是从节点slaveentry。getKey()!MixAll。MASTERID;置为truefoundtrue;}}if(found){返回数据returnnewFindBrokerResult(brokerAddr,slave,findBrokerVersion(brokerName,brokerAddr));}returnnull;}}
  回到updateConsumeOffsetToBroker方法,先看第一次调用findBrokerAddressInSubscribe方法获取Broker信息,传入的三个参数分别为:Broker名称、Master节点的ID、true,根据上面讲解的findBrokerAddressInSubscribe方法里面的查找逻辑,如果查找到Master节点的信息,就正常返回,如果此时Master宕机未能正常查找到,由于传入的Master节点的ID并且onlyThisBroker置为true,所以会查找失败返回NULL。
  如果第一次调用为空,会进行第二次调用,与第一次调用不同的地方是第三个参数置为了false,也就是说不是必须选择参数中指定的那个Broker,此时依旧优先查找Master节点,如果Master节点未查找到,由于onlyThisBroker置为了false,会迭代集合选择第一个节点返回,此时返回的有可能是从节点。
  总结:消费者会优先选择向主节点发送请求进行消费进度保存,假如主节点宕机等原因未能获取到主节点的信息,会迭代集合选择第一个节点返回,所以消费者也可以向从节点发送请求进行进度保存,待主节点恢复后,依旧优先选择主节点。publicclassRemoteBrokerOffsetStoreimplementsOffsetStore{privatevoidupdateConsumeOffsetToBroker(MessageQueuemq,longoffset)throwsRemotingException,MQBrokerException,InterruptedException,MQClientException{更新消费进度updateConsumeOffsetToBroker(mq,offset,true);}OverridepublicvoidupdateConsumeOffsetToBroker(MessageQueuemq,longoffset,booleanisOneway)throwsRemotingException,MQBrokerException,InterruptedException,MQClientException{第一次调用findBrokerAddressInSubscribe方法获取Broker信息,三个参数分别为:Broker名称、Master节点的ID、trueFindBrokerResultfindBrokerResultthis。mQClientFactory。findBrokerAddressInSubscribe(mq。getBrokerName(),MixAll。MASTERID,true);如果获取为空,进行第二次调用if(nullfindBrokerResult){三个参数分别为:Broker名称、Master节点的ID、falsethis。mQClientFactory。updateTopicRouteInfoFromNameServer(mq。getTopic());findBrokerResultthis。mQClientFactory。findBrokerAddressInSubscribe(mq。getBrokerName(),MixAll。MASTERID,false);}if(findBrokerResult!null){设置请求头UpdateConsumerOffsetRequestHeaderrequestHeadernewUpdateConsumerOffsetRequestHeader();requestHeader。setTopic(mq。getTopic());requestHeader。setConsumerGroup(this。groupName);requestHeader。setQueueId(mq。getQueueId());requestHeader。setCommitOffset(offset);发送保存消费进度的请求if(isOneway){this。mQClientFactory。getMQClientAPIImpl()。updateConsumerOffsetOneway(findBrokerResult。getBrokerAddr(),requestHeader,10005);}else{this。mQClientFactory。getMQClientAPIImpl()。updateConsumerOffset(findBrokerResult。getBrokerAddr(),requestHeader,10005);}}else{thrownewMQClientException(Thebroker〔mq。getBrokerName()〕notexist,null);}}}主从模式下的消费进度同步
  BrokerController在构造函数中,实例化了SlaveSynchronize,并在start方法中调用了handleSlaveSynchronize方法处理从节点的数据同步,
  如果当前的Broker是从节点,会注册定时任务,定时调用SlaveSynchronize的syncAll方法进行数据同步:publicclassBrokerController{privatefinalSlaveSynchronizeslaveSynchronize;publicBrokerController(finalBrokerConfigbrokerConfig,finalNettyServerConfignettyServerConfig,finalNettyClientConfignettyClientConfig,finalMessageStoreConfigmessageStoreConfig){。。。this。slaveSynchronizenewSlaveSynchronize(this);。。。}publicvoidstart()throwsException{if(!messageStoreConfig。isEnableDLegerCommitLog()){startProcessorByHa(messageStoreConfig。getBrokerRole());处理从节点的同步handleSlaveSynchronize(messageStoreConfig。getBrokerRole());this。registerBrokerAll(true,false,true);}}privatevoidhandleSlaveSynchronize(BrokerRolerole){如果是SLAVE节点if(roleBrokerRole。SLAVE){if(null!slaveSyncFuture){slaveSyncFuture。cancel(false);}this。slaveSynchronize。setMasterAddr(null);设置定时任务,定时进行数据同步slaveSyncFuturethis。scheduledExecutorService。scheduleAtFixedRate(newRunnable(){Overridepublicvoidrun(){try{同步数据BrokerController。this。slaveSynchronize。syncAll();}catch(Throwablee){log。error(ScheduledTaskSlaveSynchronizesyncAllerror。,e);}}},10003,100010,TimeUnit。MILLISECONDS);}else{handletheslavesynchroniseif(null!slaveSyncFuture){slaveSyncFuture。cancel(false);}this。slaveSynchronize。setMasterAddr(null);}}}
  在SlaveSynchronize的syncAll方法中,又调用了syncConsumerOffset方法同步消费进度:向主节点发送请求获取消费进度数据;从节点将获取到的消费进度数据进行持久化;publicclassSlaveSynchronize{publicvoidsyncAll(){this。syncTopicConfig();同步消费进度this。syncConsumerOffset();this。syncDelayOffset();this。syncSubscriptionGroupConfig();}privatevoidsyncConsumerOffset(){StringmasterAddrBakthis。masterAddr;if(masterAddrBak!null!masterAddrBak。equals(brokerController。getBrokerAddr())){try{向主节点发送请求获取消费进度信息ConsumerOffsetSerializeWrapperoffsetWrapperthis。brokerController。getBrokerOuterAPI()。getAllConsumerOffset(masterAddrBak);设置数据this。brokerController。getConsumerOffsetManager()。getOffsetTable()。putAll(offsetWrapper。getOffsetTable());将获取到的消费进度数据进行持久化this。brokerController。getConsumerOffsetManager()。persist();log。info(Updateslaveconsumeroffsetfrommaster,{},masterAddrBak);}catch(Exceptione){log。error(SyncConsumerOffsetException,{},masterAddrBak,e);}}}}
  参考
  丁威、周继锋《RocketMQ技术内幕》

3外援到齐!上海男篮闭关合练,新赛季还能起飞吗?北京时间11月29日,根据上海男篮的公示,我俱乐部与约翰尼奥布莱恩特签约。而且为球员办理入境手续,奥布莱恩特将在上海完成相关防疫要求的隔离后与球队会合,后续俱乐部将为其办理联盟注册丁俊晖单杆88分清台,上演超级大逆转,11追平乔伊斯文水清清北京时间11月29日,2022苏格兰公开赛32强争夺战,丁俊晖第2局上演超级大逆转,在052落后的情况下,单杆88分直接清台,将大比分扳成11平。丁俊晖第2局逆转乔伊斯第一世界杯第二轮结束,6支亚洲球队恐全部出局,巴西法国最具冠军相卡塔尔世界杯小组赛第二轮的全部16场比赛已经战罢,那么第二轮的比赛中,整体的比赛精彩程度远远超过了第一轮,因为很多第一轮还没有进入状态并且表现不太好的球队,在第二轮中也为了小组出线姚明在奢华酒店满脸不悦!无视路人围堵坐豪车离开,曾怒吼偷拍者饿了吗?戳右边关注我们,每天给您送上最新出炉的娱乐硬核大餐!11月29日,有网友在社交账号上晒出一段视频,曝光自己在福州偶遇姚明的画面,引发持续热议。据悉,姚明此次现身福州是为了参C罗的三个女儿二个儿子未婚女朋友,非常幸福的一个大家庭C罗是网友们非常喜欢的一个球星,特别是他的五个孩子,大儿子叫克里斯蒂亚诺罗纳尔多多斯桑托斯,网友们给他取个小名叫迷你罗,很多网友都很好奇迷你罗的的妈妈到底是谁?因为C有过十多任女朋德国门将KevinTrapp帅到蕾哈娜都招架不住比赛失利就拒绝爱爱2022世界杯激战正酣,让众多女球迷垂涎欲滴的球员数不胜数,今天我们来舔一下这位来自德国的最帅门将凯文特拉普(KevinTrapp)。其熟男外型搭配189公分的壮硕身材,一票女球迷西部排名榜太阳榜首,勇士赛季首进前8湖人耻败,布克创纪录11月29日,NBA常规赛正在如火如荼的进行中,10场激烈的比赛结束后,西部排名榜最新情况如下太阳5连胜,领跑西部排名榜,当家球星布克再创新纪录卫冕冠军勇士躺赢,赛季首次挺进前8名孙兴慜流泪被韩国网友痛骂?韩国主帅输球不满裁判被红牌罚下2022世界杯赛后孙兴慜被韩国网友痛骂?孙兴慜遭韩国网民网暴可悲的是他代表韩国人代表亚洲人在这个领域大放异彩的时候,人们只会认为他给他们争了光。当他的状态进入低迷的阶段时,那些跟着街拍黄浦银杏掩映下的这条小马路,唯美大片正在上演在黄浦,一条不长的小马路,每年的这个时期,会迎来她一年中的颜值巅峰。两旁银杏树几乎遮盖了整条马路,远远望去,如秋天里的童话。银杏叶掩映着路旁的店招店牌,微风摇曳中,相互诉说着这个季你已被移入今年最强寒潮群聊冷冬提振秋冬服饰需求11月28日,中央气象台发布寒潮橙色预警,11月28日至30日,受寒潮影响,我国中东部地区将自北向南出现剧烈降温大风沙尘和大范围雨雪天气。大部地区有46级偏北风,阵风79级气温先后女孩子洗丝袜会不会只洗脚趾部分?穿丝袜和短裙的女孩给人的印象就不用说了,但是脚上丝袜的味道却是一言难尽。虽然有各种各样的好看丝袜,但有些丝袜只是看起来很薄很透气,但其实一点也不透气。即便是透气,穿一整天后脚趾的部
凯西艾维的传球和投篮很棒,想派斯图尔特杜伦同时出场活塞主教练德韦恩凯西接受媒体采访,谈到了活塞球员杰登艾维。我对艾维的投篮和传球能力感到印象深刻。凯西在采访中表示。他这两项能力比我在通过录像考察他时所看到的还要更好。在谈到球队时,山东队赢了上海队19分!来看看赛后,王晗和李春江讲了什么?山东队大胜上海队19分,收获2连胜CBA常规赛第七轮,在此前遭到了四连败的上海队面对实力不俗的山东队,结果,上海队依然没有摆脱输球的厄运,双方四节比赛打完,以87106输给了山东队中国男篮后卫线重组!赵继伟退出,郭艾伦无缘,广东宏远挑大梁问如何每天都能收到如此有趣的体育原创资讯?答只需轻点右上角的关注按钮就能实现梦想。CBA第一阶段的比赛已经接近尾声,接下来备受球迷关注当然是世预赛,第五窗口期中国男篮将对阵伊朗和巴如果巴萨输球就告别欧冠,欧冠巴塞罗那VS拜仁慕尼黑北京时间2022年10月27日03点00分欧冠小组迎来一场焦点大战,巴塞罗那主场战拜仁慕尼黑。不过这场强强对战对小组大局却没有多大的影响,目前巴萨已经没有出线主动权,本轮国米赢下皮一碗驱寒汤,逼出体内陈年旧寒,通脉温血通全身如果你关节怕凉,而且在天气稍有变化后,就有关节疼痛加剧身体不适的情况,那你一定要看这篇文章。天气变冷,对有关节病的患者来讲,可是难熬的一件事情。后台很多骨病患者留言说自己的关节疼痛蓝天白云,红花绿叶,怡神养心,美不胜收世界上最美丽的图画在哪里?那一定得去大自然中寻找,因为大自然是一个神奇的画家魔术师。大自然能绘制出五彩斑斓的颜色,大自然能变换出神奇美丽的风景。每当我们置身于大自然,都会被它美丽的暗能量与暗物质获迄今最精确计算美国天体物理学家的一项分析,对宇宙的组成和演化设置了迄今为止最精确的限制。通过这种被称为Pantheon的分析,宇宙学家确认宇宙由大约三分之二的暗能量和三分之一的物质组成,这种物质体内有湿还有痰?千古名方三仁汤,上可宣肺,中可健脾,下利膀胱大家好,我是刘医生。体内痰湿太重,一直是现代人很头疼的一个问题。经常感觉喉咙里面有痰,还经常流鼻涕,特别容易感冒,大便总是稀的,小肚子也比较大。这时伸出舌头看一下会发现舌头很胖大,鸡蛋吃多了,会升高体内胆固醇吗?做好这4件事,或许有益处小小的鸡蛋蕴含着无限的能量,被营养学家称为理想的营养库,鸡蛋是人们眼中的营养美味食物,很多人都喜欢吃,不论是清炒还是煎炸或是水煮,都让人垂涎三尺。就是这么好的鸡蛋,还有人把它称为坏Nature利用量子纠缠,物质波干涉仪首超标准量子极限量子力学中有许多奇怪而反直觉的效应。比如,爱因斯坦将量子纠缠称为鬼魅般的超距作用,简单理解,这种效应说的是,一个原子发生的事情会以某种方式影响其他地方的另一个原子。它已经成为量子计寻找暗物质暗能量中国建立世界最深极深实验室深度2400米振奋国人的好消息!近日有媒体报道中国建立了首个极深地下实验室,真是可喜可贺。那么我国为什么要建立这样的实验室呢?就是为了寻找研究深度太空中看不见摸不着的暗物质暗能量。我们先来说一下
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网