国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網(wǎng)易首頁(yè) > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

求求你們別再用 kill -9 了,這才是 Spring Boot 停機(jī)的正確方式!

0
分享至

Java精選面試題(微信小程序):5000+道面試題和選擇題,真實(shí)面經(jīng),簡(jiǎn)歷模版,包含Java基礎(chǔ)、并發(fā)、JVM、線程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架構(gòu)設(shè)計(jì)、大廠真題等,在線隨時(shí)刷題!

再談為了提醒明知故犯(在一坑里迭倒兩次不是不多見),由于業(yè)務(wù)系統(tǒng)中大量使用了spring Boot embedded tomcat的模式運(yùn)行,在一些運(yùn)維腳本中經(jīng)??吹絃inux 中 kill 指令,然而它的使用也有些講究,要思考如何能做到優(yōu)雅停機(jī)。

1. 何為優(yōu)雅關(guān)機(jī)

就是為確保應(yīng)用關(guān)閉時(shí),通知應(yīng)用進(jìn)程釋放所占用的資源

  • 線程池,shutdown(不接受新任務(wù)等待處理完)還是shutdownNow(調(diào)用 Thread.interrupt進(jìn)行中斷)

  • socket 鏈接,比如:netty、mq

  • 告知注冊(cè)中心快速下線(靠心跳機(jī)制客服早都跳起來了),比如:eureka

  • 清理臨時(shí)文件,比如:poi

  • 各種堆內(nèi)堆外內(nèi)存釋放

總之,進(jìn)程強(qiáng)行終止會(huì)帶來數(shù)據(jù)丟失或者終端無法恢復(fù)到正常狀態(tài),在分布式環(huán)境下還可能導(dǎo)致數(shù)據(jù)不一致的情況。

2. kill 指令

kill -9 pid可以模擬了一次系統(tǒng)宕機(jī),系統(tǒng)斷電等極端情況,而kill -15 pid則是等待應(yīng)用關(guān)閉,執(zhí)行阻塞操作,有時(shí)候也會(huì)出現(xiàn)無法關(guān)閉應(yīng)用的情況(線上理想情況下,是bug就該尋根溯源)

#查看jvm進(jìn)程pid jps #列出所有信號(hào)名稱 kill -l > 基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能 > > * 項(xiàng)目地址: //github.com/YunaiV/yudao-cloud> > * 視頻教程: //doc.iocoder.cn/video/> # Windows下信號(hào)常量值 # 簡(jiǎn)稱  全稱    數(shù)值  # INT   SIGINT      2        Ctrl+C中斷 # ILL   SIGILL      4        非法指令 # FPE   SIGFPE      8         floating point exception(浮點(diǎn)異常) # SEGV  SIGSEGV    11      segment violation(段錯(cuò)誤) # TERM  SIGTERM    5       Software termination signal from kill(Kill發(fā)出的軟件終止) # BREAK SIGBREAK   21      Ctrl-Break sequence(Ctrl+Break中斷) # ABRT  SIGABRT    22      abnormal termination triggered by abort call(Abort) #linux信號(hào)常量值 # 簡(jiǎn)稱  全稱  數(shù)值   # HUP   SIGHUP      1    終端斷線   # INT   SIGINT      2    中斷(同 Ctrl + C)         # QUIT  SIGQUIT     3    退出(同 Ctrl + \)          # KILL  SIGKILL     9    強(qiáng)制終止          # TERM  SIGTERM     15    終止          # CONT  SIGCONT     18    繼續(xù)(與STOP相反, fg/bg命令)          # STOP  SIGSTOP     19    暫停(同 Ctrl + Z)         #.... #可以理解為操作系統(tǒng)從內(nèi)核級(jí)別強(qiáng)行殺死某個(gè)進(jìn)程 kill -9 pid  #理解為發(fā)送一個(gè)通知,等待應(yīng)用主動(dòng)關(guān)閉 kill -15 pid #也支持信號(hào)常量值全稱或簡(jiǎn)寫(就是去掉SIG后) kill -l KILL

思考:jvm是如何接受處理linux信號(hào)量的?

當(dāng)然是在jvm啟動(dòng)時(shí)就加載了自定義SignalHandler,關(guān)閉jvm時(shí)觸發(fā)對(duì)應(yīng)的handle。

public interface SignalHandler{     SignalHandler SIG_DFL = new NativeSignalHandler(0L);     SignalHandler SIG_IGN = new NativeSignalHandler(1L);     voidhandle(Signal var1); } class Terminator{     privatestatic SignalHandler handler = null;     Terminator() {     }     //jvm設(shè)置SignalHandler,在System.initializeSystemClass中觸發(fā)     staticvoidsetup(){         if (handler == null) {             SignalHandler var0 = new SignalHandler() {                 publicvoidhandle(Signal var1){                     Shutdown.exit(var1.getNumber() + 128);//調(diào)用Shutdown.exit                 }             };             handler = var0;             try {                 Signal.handle(new Signal("INT"), var0);//中斷時(shí)             } catch (IllegalArgumentException var3) {                 ;             }             try {                 Signal.handle(new Signal("TERM"), var0);//終止時(shí)             } catch (IllegalArgumentException var2) {                 ;             }         }     } }

Runtime.addShutdownHook

在了解Shutdown.exit之前,先看Runtime.getRuntime().addShutdownHook(shutdownHook);則是為jvm中增加一個(gè)關(guān)閉的鉤子,當(dāng)jvm關(guān)閉的時(shí)候調(diào)用。

publicclassRuntime{     publicvoidaddShutdownHook(Thread hook){         SecurityManager sm = System.getSecurityManager();         if (sm != null) {             sm.checkPermission(new RuntimePermission("shutdownHooks"));         }         ApplicationShutdownHooks.add(hook);     } } classApplicationShutdownHooks{     /* The set of registered hooks */     privatestatic IdentityHashMap hooks;     staticsynchronizedvoidadd(Thread hook){         if(hooks == null)             thrownew IllegalStateException("Shutdown in progress");         if (hook.isAlive())             thrownew IllegalArgumentException("Hook already running");         if (hooks.containsKey(hook))             thrownew IllegalArgumentException("Hook previously registered");         hooks.put(hook, hook);     } } //它含數(shù)據(jù)結(jié)構(gòu)和邏輯管理虛擬機(jī)關(guān)閉序列 classShutdown{     /* Shutdown 系列狀態(tài)*/     privatestaticfinalint RUNNING = 0;     privatestaticfinalint HOOKS = 1;     privatestaticfinalint FINALIZERS = 2;     privatestaticint state = RUNNING;     /* 是否應(yīng)該運(yùn)行所以finalizers來exit? */     privatestaticboolean runFinalizersOnExit = false;     // 系統(tǒng)關(guān)閉鉤子注冊(cè)一個(gè)預(yù)定義的插槽.     // 關(guān)閉鉤子的列表如下:     // (0) Console restore hook     // (1) Application hooks     // (2) DeleteOnExit hook     privatestaticfinalint MAX_SYSTEM_HOOKS = 10;     privatestaticfinal Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS];     // 當(dāng)前運(yùn)行關(guān)閉鉤子的鉤子的索引     privatestaticint currentRunningHook = 0;     /* 前面的靜態(tài)字段由這個(gè)鎖保護(hù) */     privatestaticclassLock{ };     privatestatic Object lock = new Lock();     /* 為native halt方法提供鎖對(duì)象 */     privatestatic Object haltLock = new Lock();     staticvoidadd(int slot, boolean registerShutdownInProgress, Runnable hook){         synchronized (lock) {             if (hooks[slot] != null)                 thrownew InternalError("Shutdown hook at slot " + slot + " already registered");             if (!registerShutdownInProgress) {//執(zhí)行shutdown過程中不添加hook                 if (state > RUNNING)//如果已經(jīng)在執(zhí)行shutdown操作不能添加hook                     thrownew IllegalStateException("Shutdown in progress");             } else {//如果hooks已經(jīng)執(zhí)行完畢不能再添加hook。如果正在執(zhí)行hooks時(shí),添加的槽點(diǎn)小于當(dāng)前執(zhí)行的槽點(diǎn)位置也不能添加                 if (state > HOOKS || (state == HOOKS && slot <= currentRunningHook))                     thrownew IllegalStateException("Shutdown in progress");             }             hooks[slot] = hook;         }     }     /* 執(zhí)行所有注冊(cè)的hooks      */     privatestaticvoidrunHooks(){         for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {             try {                 Runnable hook;                 synchronized (lock) {                     // acquire the lock to make sure the hook registered during                     // shutdown is visible here.                     currentRunningHook = i;                     hook = hooks[i];                 }                 if (hook != null) hook.run();             } catch(Throwable t) {                 if (t instanceof ThreadDeath) {                     ThreadDeath td = (ThreadDeath)t;                     throw td;                 }             }         }     }     /* 關(guān)閉JVM的操作      */     staticvoidhalt(int status){         synchronized (haltLock) {             halt0(status);         }     }     //JNI方法     staticnativevoidhalt0(int status);     // shutdown的執(zhí)行順序:runHooks > runFinalizersOnExit     privatestaticvoidsequence(){         synchronized (lock) {             /* Guard against the possibility of a daemon thread invoking exit              * after DestroyJavaVM initiates the shutdown sequence              */             if (state != HOOKS) return;         }         runHooks();         boolean rfoe;         synchronized (lock) {             state = FINALIZERS;             rfoe = runFinalizersOnExit;         }         if (rfoe) runAllFinalizers();     }     //Runtime.exit時(shí)執(zhí)行,runHooks > runFinalizersOnExit > halt     staticvoidexit(int status){         boolean runMoreFinalizers = false;         synchronized (lock) {             if (status != 0) runFinalizersOnExit = false;             switch (state) {             case RUNNING:       /* Initiate shutdown */                 state = HOOKS;                 break;             case HOOKS:         /* Stall and halt */                 break;             case FINALIZERS:                 if (status != 0) {                     /* Halt immediately on nonzero status */                     halt(status);                 } else {                     /* Compatibility with old behavior:                      * Run more finalizers and then halt                      */                     runMoreFinalizers = runFinalizersOnExit;                 }                 break;             }         }         if (runMoreFinalizers) {             runAllFinalizers();             halt(status);         }         synchronized (Shutdown.class) {             /* Synchronize on the class object, causing any other thread              * that attempts to initiate shutdown to stall indefinitely              */             sequence();             halt(status);         }     }     //shutdown操作,與exit不同的是不做halt操作(關(guān)閉JVM)     staticvoidshutdown(){         synchronized (lock) {             switch (state) {             case RUNNING:       /* Initiate shutdown */                 state = HOOKS;                 break;             case HOOKS:         /* Stall and then return */             case FINALIZERS:                 break;             }         }         synchronized (Shutdown.class) {             sequence();         }     } }

spring 3.2.12

在spring中通過ContextClosedEvent事件來觸發(fā)一些動(dòng)作(可以拓展),主要通過LifecycleProcessor.onClose來做stopBeans。由此可見spring也基于jvm做了拓展。

publicabstractclassAbstractApplicationContextextendsDefaultResourceLoader{ publicvoidregisterShutdownHook(){ if (this.shutdownHook == null) {    // No shutdown hook registered yet.    this.shutdownHook = new Thread() {     @Override     publicvoidrun(){      doClose();     }    };    Runtime.getRuntime().addShutdownHook(this.shutdownHook);   }  } protectedvoiddoClose(){ boolean actuallyClose; synchronized (this.activeMonitor) {    actuallyClose = this.active && !this.closed;    this.closed = true;   } if (actuallyClose) {    if (logger.isInfoEnabled()) {     logger.info("Closing " + this);    }    LiveBeansView.unregisterApplicationContext(this);    try {     //發(fā)布應(yīng)用內(nèi)的關(guān)閉事件     publishEvent(new ContextClosedEvent(this));    }    catch (Throwable ex) {     logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);    }    // 停止所有的Lifecycle beans.    try {     getLifecycleProcessor().onClose();    }    catch (Throwable ex) {     logger.warn("Exception thrown from LifecycleProcessor on context close", ex);    }    // 銷毀spring 的 BeanFactory可能會(huì)緩存單例的 Bean.    destroyBeans();    // 關(guān)閉當(dāng)前應(yīng)用上下文(BeanFactory)    closeBeanFactory();    // 執(zhí)行子類的關(guān)閉邏輯    onClose();    synchronized (this.activeMonitor) {     this.active = false;    }   }  }  } publicinterfaceLifecycleProcessorextendsLifecycle{ /**   * Notification of context refresh, e.g. for auto-starting components.   */ voidonRefresh(); /**   * Notification of context close phase, e.g. for auto-stopping components.   */ voidonClose(); }

spring boot

到這里就進(jìn)入重點(diǎn)了,spring boot中有spring-boot-starter-actuator模塊提供了一個(gè) restful 接口,用于優(yōu)雅停機(jī)。執(zhí)行請(qǐng)求 curl -X POST http://127.0.0.1:8088/shutdown,待關(guān)閉成功則返回提示。

注:線上環(huán)境該url需要設(shè)置權(quán)限,可配合 spring-security使用或在nginx中限制內(nèi)網(wǎng)訪問。

#啟用shutdown endpoints.shutdown.enabled=true #禁用密碼驗(yàn)證 endpoints.shutdown.sensitive=false #可統(tǒng)一指定所有endpoints的路徑 management.context-path=/manage #指定管理端口和IP management.port=8088 management.address=127.0.0.1 #開啟shutdown的安全驗(yàn)證(spring-security) endpoints.shutdown.sensitive=true #驗(yàn)證用戶名 security.user.name=admin #驗(yàn)證密碼 security.user.password=secret #角色 management.security.role=SUPERUSER

spring boot的shutdown原理也不復(fù)雜,其實(shí)還是通過調(diào)用AbstractApplicationContext.close實(shí)現(xiàn)的。

@ConfigurationProperties(     prefix = "endpoints.shutdown" ) publicclassShutdownMvcEndpointextendsEndpointMvcAdapter{     publicShutdownMvcEndpoint(ShutdownEndpoint delegate){         super(delegate);     }     //post請(qǐng)求     @PostMapping(         produces = {"application/vnd.spring-boot.actuator.v1+json", "application/json"}     )     @ResponseBody     public Object invoke(){         return !this.getDelegate().isEnabled() ? new ResponseEntity(Collections.singletonMap("message", "This endpoint is disabled"), HttpStatus.NOT_FOUND) : super.invoke();     } } @ConfigurationProperties(     prefix = "endpoints.shutdown" ) publicclassShutdownEndpointextendsAbstractEndpoint

 > implementsApplicationContextAware{     privatestaticfinal Map NO_CONTEXT_MESSAGE = Collections.unmodifiableMap(Collections.singletonMap( "message", "No context to shutdown."));     privatestaticfinal Map SHUTDOWN_MESSAGE = Collections.unmodifiableMap(Collections.singletonMap( "message", "Shutting down, bye..."));     private ConfigurableApplicationContext context;     publicShutdownEndpoint(){         super("shutdown", true, false);     }     //執(zhí)行關(guān)閉     public Map   invoke(){         if (this.context == null) {             return NO_CONTEXT_MESSAGE;         } else {             boolean var6 = false;             Map var1;             classNamelessClass_1implementsRunnable{                 NamelessClass_1() {                 }                 publicvoidrun(){                     try {                         Thread.sleep(500L);                     } catch (InterruptedException var2) {                         Thread.currentThread().interrupt();                     }                     //這個(gè)調(diào)用的就是AbstractApplicationContext.close                     ShutdownEndpoint.this.context.close();                 }             }             try {                 var6 = true;                 var1 = SHUTDOWN_MESSAGE;                 var6 = false;             } finally {                 if (var6) {                     Thread thread = new Thread(new NamelessClass_1());                     thread.setContextClassLoader(this.getClass().getClassLoader());                     thread.start();                 }             }             Thread thread = new Thread(new NamelessClass_1());             thread.setContextClassLoader(this.getClass().getClassLoader());             thread.start();             return var1;         }     } }

引用資料:https://linux.die.net/man/1/kill

作者:布道

來源:https://juejin.cn/post/7394073179483947008

公眾號(hào)“Java精選”所發(fā)表內(nèi)容注明來源的,版權(quán)歸原出處所有(無法查證版權(quán)的或者未注明出處的均來自網(wǎng)絡(luò),系轉(zhuǎn)載,轉(zhuǎn)載的目的在于傳遞更多信息,版權(quán)屬于原作者。如有侵權(quán),請(qǐng)聯(lián)系,筆者會(huì)第一時(shí)間刪除處理!

最近有很多人問,有沒有讀者交流群!加入方式很簡(jiǎn)單,公眾號(hào)Java精選,回復(fù)“加群”,即可入群!

文章有幫助的話,點(diǎn)在看,轉(zhuǎn)發(fā)吧!

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關(guān)推薦
熱點(diǎn)推薦
美國(guó)吃華人絕戶財(cái)富已經(jīng)成為一個(gè)公開的密碼了!

美國(guó)吃華人絕戶財(cái)富已經(jīng)成為一個(gè)公開的密碼了!

達(dá)文西看世界
2026-01-24 15:32:33
中國(guó)金花距離澳網(wǎng)決賽一步之遙,女單冠軍爭(zhēng)奪戰(zhàn)逐漸明朗

中國(guó)金花距離澳網(wǎng)決賽一步之遙,女單冠軍爭(zhēng)奪戰(zhàn)逐漸明朗

體育豐蘊(yùn)
2026-01-29 16:08:58
國(guó)產(chǎn)固態(tài)電池量產(chǎn)加速!數(shù)千萬(wàn)新能源車主,恐成最大“接盤俠”?

國(guó)產(chǎn)固態(tài)電池量產(chǎn)加速!數(shù)千萬(wàn)新能源車主,恐成最大“接盤俠”?

胖福的小木屋
2026-01-28 10:43:40
剖人心者終被食:亂世惡棍張彥澤的結(jié)局比電視上還慘

剖人心者終被食:亂世惡棍張彥澤的結(jié)局比電視上還慘

愛歷史
2026-01-28 10:07:37
價(jià)格大跳水!主力車型直降超15萬(wàn),中年男人的夢(mèng)中豪車撐不住了?

價(jià)格大跳水!主力車型直降超15萬(wàn),中年男人的夢(mèng)中豪車撐不住了?

財(cái)經(jīng)八卦
2026-01-28 20:05:03
女子用剁椒魚頭試探“網(wǎng)戀男友”,仍被騙68萬(wàn)

女子用剁椒魚頭試探“網(wǎng)戀男友”,仍被騙68萬(wàn)

中國(guó)日?qǐng)?bào)
2026-01-29 12:00:59
編程門檻被壓到799美元?“那個(gè)拿著Mac Mini+Claude的「門外漢」,搶走了程序員3個(gè)月的活!”

編程門檻被壓到799美元?“那個(gè)拿著Mac Mini+Claude的「門外漢」,搶走了程序員3個(gè)月的活!”

CSDN
2026-01-27 18:10:04
阿富汗塔利班恢復(fù)奴隸制?

阿富汗塔利班恢復(fù)奴隸制?

孫曉宇
2026-01-28 14:18:17
貝森特再點(diǎn)卡尼:你這種人我見得多了,別搞事

貝森特再點(diǎn)卡尼:你這種人我見得多了,別搞事

觀察者網(wǎng)
2026-01-29 08:51:38
周總理逝世21年后,中國(guó)銀行核查賬目時(shí)發(fā)現(xiàn)他名下存有巨額存款,一番調(diào)查后揭開了背后的真相

周總理逝世21年后,中國(guó)銀行核查賬目時(shí)發(fā)現(xiàn)他名下存有巨額存款,一番調(diào)查后揭開了背后的真相

寄史言志
2026-01-17 16:37:15
無法復(fù)制的價(jià)值!95年喬丹第一次復(fù)出有多轟動(dòng)?魔術(shù)師曾為他下跪

無法復(fù)制的價(jià)值!95年喬丹第一次復(fù)出有多轟動(dòng)?魔術(shù)師曾為他下跪

禾三千體育
2026-01-29 16:42:32
要打就打痛!中國(guó)手段已升級(jí),日本:中方不批準(zhǔn)駐重慶總領(lǐng)事任命

要打就打痛!中國(guó)手段已升級(jí),日本:中方不批準(zhǔn)駐重慶總領(lǐng)事任命

墨蘭史書
2026-01-28 20:45:03
偉大的2-0!中國(guó)金花直通澳網(wǎng)決賽:解鎖2大成就,爭(zhēng)冠對(duì)手確定!

偉大的2-0!中國(guó)金花直通澳網(wǎng)決賽:解鎖2大成就,爭(zhēng)冠對(duì)手確定!

劉姚堯的文字城堡
2026-01-29 16:33:24
本期禁足名單分布:31名球員、6名教練、17名足協(xié)官員、1名裁判

本期禁足名單分布:31名球員、6名教練、17名足協(xié)官員、1名裁判

慢歌輕步謠
2026-01-29 14:03:07
陳永貴夫人宋玉林離世,葬禮之上郭鳳蓮致悼詞,現(xiàn)場(chǎng)人山人海滿是悲戚

陳永貴夫人宋玉林離世,葬禮之上郭鳳蓮致悼詞,現(xiàn)場(chǎng)人山人海滿是悲戚

文史明鑒
2026-01-22 17:37:12
金價(jià)創(chuàng)新高!黃金變現(xiàn)業(yè)務(wù)爆了

金價(jià)創(chuàng)新高!黃金變現(xiàn)業(yè)務(wù)爆了

環(huán)球網(wǎng)資訊
2026-01-29 11:28:09
能否逆轉(zhuǎn)銷量?曝特斯拉即將推出Model YL+,88度電池,續(xù)航800km

能否逆轉(zhuǎn)銷量?曝特斯拉即將推出Model YL+,88度電池,續(xù)航800km

凡兮說
2026-01-29 16:44:36
大S雕像揭幕儀式即將開啟,出席人員曝光!汪小菲有望上金寶山!

大S雕像揭幕儀式即將開啟,出席人員曝光!汪小菲有望上金寶山!

娛樂團(tuán)長(zhǎng)
2026-01-29 12:26:42
再打下去,烏克蘭沒男人了!澤連斯基解禁,允許年輕男性出國(guó)避難

再打下去,烏克蘭沒男人了!澤連斯基解禁,允許年輕男性出國(guó)避難

史智文道
2026-01-29 16:22:57
阿森納全勝領(lǐng)銜 英超隊(duì)踢歐冠怎么就如此輕松?

阿森納全勝領(lǐng)銜 英超隊(duì)踢歐冠怎么就如此輕松?

體壇周報(bào)
2026-01-29 16:16:23
2026-01-29 17:23:00
Java精選
Java精選
一場(chǎng)永遠(yuǎn)也演不完的戲
1768文章數(shù) 3859關(guān)注度
往期回顧 全部

科技要聞

周亞輝的AI新賭局:國(guó)內(nèi)太卷 出海另起爐灶

頭條要聞

女大學(xué)生到東北游玩暈倒雪地凍傷 三根手指或面臨截肢

頭條要聞

女大學(xué)生到東北游玩暈倒雪地凍傷 三根手指或面臨截肢

體育要聞

詹姆斯哭了!騎士視頻致敬41歲超巨

娛樂要聞

張譯不再隱瞞!公開回應(yīng)退圈息影真相

財(cái)經(jīng)要聞

崔東樹:中國(guó)汽車未來年銷或達(dá)5000萬(wàn)輛

汽車要聞

車長(zhǎng)超5米還帶后輪轉(zhuǎn)向 比亞迪海豹08/海獅08將亮相

態(tài)度原創(chuàng)

家居
親子
手機(jī)
健康
軍事航空

家居要聞

極簡(jiǎn)輕奢 家的無限可能

親子要聞

一個(gè)現(xiàn)象:縣城里的孕婦越來越少了

手機(jī)要聞

游戲直播神器!iQOO 15 Ultra支持一鍵投屏 開播0門檻

耳石癥分類型,癥狀大不同

軍事要聞

中國(guó)代表:支持伊朗國(guó)家穩(wěn)定 武力解決不了問題

無障礙瀏覽 進(jìn)入關(guān)懷版