自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

在線“殺死” App 的卡頓難題!

原創(chuàng)
移動開發(fā) Android 系統(tǒng)運維
本?將為大家分享作者是如何在?個?內(nèi)降低 50% 的 ANR 線上問題發(fā)?率的探索與實踐,希望能對開發(fā)者有所幫助或啟發(fā)。

ANR(Application Not Response)是安卓開發(fā)團(tuán)隊經(jīng)常遇到的無響應(yīng)問題,但卻很難定位和根除。尤其是線上問題,由于難以復(fù)現(xiàn),導(dǎo)致開發(fā)者難以有效地快速解決。為此,本?將為大家分享作者是如何在?個?內(nèi)降低 50% 的 ANR 線上問題發(fā)?率的探索與實踐,希望能對開發(fā)者有所幫助或啟發(fā)。

Google 的一項內(nèi)部研究表明,過高的崩潰與 ANR 發(fā)生率會直接影響應(yīng)用的評分情況,并且很難在商店中累積起用戶量,嚴(yán)重影響應(yīng)用在商店的排名情況。這一系列的連鎖反應(yīng)將會給應(yīng)用帶來很大的損失,且有可能失去在應(yīng)用商店獲得谷歌推薦的資格。因此,ANR 問題對于?多數(shù)安卓團(tuán)隊來說十分棘手,尤其是線上問題令人頭疼。因為本地問題可以復(fù)現(xiàn),線上 ANR 卻很難。因而探究線上 ANR 問題的治理?案更具意義。

觸因與流程分析

1. 關(guān)于 ANR

從用戶側(cè)看, ANR 問題是指?戶在使?應(yīng)?過程中出現(xiàn)了嚴(yán)重卡頓或卡死時,系統(tǒng)給出的?響應(yīng)提示彈窗。而從系統(tǒng)側(cè)看,ANR 問題就是 AMS 在執(zhí)?特定?法時出現(xiàn)的超時錯誤,觸發(fā)點有四個:

  • InputDispatching Timeout
  • BroadcastQueue Timeout
  • Service Timeout
  • ContentProvider Timeout

系統(tǒng)的 ANR 觸發(fā)流程?致可分為兩個部分:

?戶可以直觀感受到的 ANR 彈窗,這部分由 AMS 處理。

同時 AMS 還會發(fā)出?個 SIGQUIT 信號:  SignalCatcher 線程會接收到這個信號,并且處理后續(xù)的 dump 邏輯;市?上的 ANR 錯誤收集 SDK?部分都依賴于這個原理。

2. 現(xiàn)狀與挑戰(zhàn)

根據(jù)美圖秀秀 Android 端的線上監(jiān)控數(shù)據(jù)表現(xiàn), ANR 問題?乎是崩潰問題的兩倍。在這種情況下,?先要考慮的就是如何將問題數(shù)量降低,然后再考慮后續(xù)?案。

?對大批問題,?先就是對數(shù)據(jù)進(jìn)?分析、歸類和梳理以便找出頭部問題。美圖秀秀的線上頭部問題分布如下:

這些問題經(jīng)過簡單分析后,得出了如下結(jié)論:

nativePollOnce 問題,暫時不能依賴現(xiàn)有的?志信息得出結(jié)論。不過其占?較?,要放在?優(yōu)先級處理。processPendingWork 問題已經(jīng)有可靠的處理?案。占?不低,應(yīng)該放在較?的優(yōu)先級處理。

剩余問題數(shù)量相近,所以處理順序并不固定。

分析與實踐

在分析具體問題之前,?先跟?家分享?下筆者在處理問題過程中總結(jié)的?些經(jīng)驗。

我們遇到的絕?部分問題,都可以分為兩類:

有源問題:是指可以直接溯源、定位到的問題;有源問題通??梢灾苯咏鉀Q,其處理結(jié)果直接影響到線上的某個指標(biāo)(如:相應(yīng)問題的發(fā)?次數(shù),發(fā)?率等等)

?源問題:問題成因不定且沒有確定的線索;?對?源問題更多時候需要“?膽假設(shè),??求證” 。通常?源問題需要更多的現(xiàn)場信息以及側(cè)?證據(jù)來溯源。成功溯源之后的?源問題可轉(zhuǎn)換成?個或 多個有源問題。

當(dāng)?系列問題有了明確的優(yōu)先級以及分類之后,我們就可以開始分析單體 Case 了。

1. MessageQueue.nativePollOnce 問題

線上上報的堆棧如上圖所示。棘手之處在于:如果只看上報的堆棧和錯誤?志,很難排查出問題的根本原因。上?提到過,處理這類問題要“?膽假設(shè)”,其可能的原因有:

  • 主線程狀態(tài)異常導(dǎo)致“停頓”
  • 卡頓堆棧漂移
  • 其他未知原因
  • 有了假設(shè)之后,就需要“??求證”了:
  • 假設(shè)主線程異常,那么因何產(chǎn)??
  • 假設(shè)卡頓堆棧漂移,那么真實的卡頓堆棧在哪??

1.1 主線程卡死情況

Android 應(yīng)?啟動過程中有這樣的?段邏輯:zygote 初始化 →RuntimeInit 初始化。在 RuntimeInit 初始化過程中會注冊?個默認(rèn)的錯誤處理器來響應(yīng)異常,如下所示:

默認(rèn)的異常處理機(jī)制會在線程發(fā)? Crash 時同步給 ActivityThread、ActivityManagerService 之后再“kill”掉?身。

那么如果當(dāng)主線程發(fā)?異常的情況下,不使?系統(tǒng)的處理鏈路或異常處理過程中耗時過久就會發(fā)? ANR。當(dāng)主線程發(fā)?了崩潰后其實已處于終?狀態(tài)。此時主線程 Looper 的 MessageQueue 組件?法繼續(xù)添加新的消息,? Android 應(yīng)?的運?恰恰依賴的就是主線程的消息輪詢 -- 線上這個錯誤堆棧也是指向了 MessageQueue 組件在等待新消息的到來。因此,當(dāng)主線程發(fā)?異常并?法及時 kill 掉進(jìn)程時,系統(tǒng)就  會觸發(fā) ANR 超時機(jī)制。按照以上的邏輯推斷,我們通過埋點找出了線上異常處理鏈的各個?法耗時數(shù)據(jù):

通過對?各個異常處理?法的耗時可以發(fā)現(xiàn),F(xiàn)irebase 異常分析 SDK 在異常處理鏈路中耗時最?。預(yù)計移除此組件可降低該問題的發(fā)?數(shù)量。

最終在去除 Firebase 異常分析 SDK 的版本上線之后,線上數(shù)據(jù)顯示整體的 ANR 率都有所下降。

接下來分析另?種情況:

1.2 卡頓堆棧漂移

在這種情況下,錯誤上報中的卡頓堆棧已經(jīng)失真,?法反映出當(dāng)時現(xiàn)場的真實的情況。因此,增加線上的慢函數(shù)監(jiān)控可以更準(zhǔn)確地分析此問題。

線上慢函數(shù)監(jiān)控的原理:

查看 Looper 的源碼得知:主線程所有執(zhí)?的任務(wù)都在 Looper.loop() ?法中的 msg.target.dispatchMessage 中派發(fā)執(zhí)?。在這?有個 Printer 組件分別在消息的執(zhí)?前、后會 有?個打印的?法調(diào)???赏ㄟ^ Looper.setMessageLogging ?法設(shè)置?個 Printer ,來監(jiān)控每   個 Message 的執(zhí)?時間:

監(jiān)控邏輯的關(guān)鍵代碼:

在后期,我們通過這種?式獲得了以下慢函數(shù)數(shù)據(jù):

整理后得到的分布數(shù)據(jù):

不難得出:

【QueuedWork.processPendingWork】、【??創(chuàng)建】類型的問題占?最?,必須優(yōu)先處理。下?將詳細(xì)分析這兩個問題。

回到上?錯誤處理的思路中:

此問題的處理中,使?了通?的?源問題處理?案。通過   【假設(shè) -> 驗證 -> 上線 ->數(shù)據(jù)變化 】這?流程,最終減少了此問題的發(fā)?或轉(zhuǎn)換成了有源問題。當(dāng)然,這個問題的誘因不只以上兩個猜想,還有更多的可能需要進(jìn)?步探索。

2. QueuedWork.processPendingWork 問題處理

問題調(diào)?棧:

對 AndroidFrameWork 源碼接觸較少的同學(xué)們,可能并不了解這個類的作?。這時候可以借助 Android 源碼搜索引擎來?看究竟:

通過對源碼的分析,可以得出?個?致流程:

SharedPreferencesImpl.apply() ?法中調(diào)?  QueuedWork.add() 將  SharedPreferences  的寫 ?任務(wù)添加進(jìn)  QueuedWork 的任務(wù)隊列中,之后 ActivityThread 在?些組件?命周期?法中執(zhí)?了 QueuedWork.waitToFinish → QueuedWork.processPendingWork 這?流程。這?個?命周期方法有:

  • handleStopService
  • handlePauseActivity
  • handleStopActivity
  • handleSleeping

以上的?命周期?法都會先等待 QueuedWork 中的異步隊列執(zhí)?完成,再執(zhí)?后續(xù)的流程。

很容易得出這樣的結(jié)論:SharedPreferences 的 apply ?法本身設(shè)計為異步寫?,?Android 系統(tǒng)為了保證數(shù)據(jù)有效性會在特定的?命周期?法中等待異步寫?任務(wù)的完成。如果這個任務(wù)處理耗時過?,就會產(chǎn)? ANR 問題

美圖秀秀內(nèi)部開發(fā)了?款代碼的織??具 MtAjx 。其類似于?家熟知的 AspectJ ,相? AspectJ ?案, 有著更好的兼容性(司內(nèi)?批項?編譯遇到 AspectJ 的問題)以及更?性化的 API 設(shè)計。

在處理這個問題時,我們使?了 MtAjx 來攔截 SharedPreferences 的創(chuàng)建,并返回帶?志輸出功能的 SharedPreferencesWrapper 。

簡化的流程如下:

要完成上?的功能,使? MtAjx 只需要編寫?些簡單的規(guī)則即可實現(xiàn):

接下來可采??動化測試來模擬線上?戶的真實操作,并通過 SharedPreferencesWrapper 的?志對SharedPreferences 寫?頻率進(jìn)?分析。

最終輸出的數(shù)據(jù)如下:


?前收集的線索可以推斷出:  GMS 組件的某個操作,?量地調(diào)?了 SharedPreferences 的 apply ?法。這個操作可能會使 SharedPreferences 的異步寫?任務(wù)創(chuàng)建過多從?導(dǎo)致 ANR。后期處理此問題時,我們對這個組件進(jìn)?了改造:使? MtAjx 在 GMS 中攔截 SharedPreferences 的創(chuàng)建、獲取操作, 并返回?個安全的 SharedPreferences 實現(xiàn)。?然上線之后,得到的數(shù)據(jù)跟預(yù)估的有些差距:

?身問題減少的?例很?

線上整體 ANR 波動不?

猜測這個問題發(fā)?時系統(tǒng)的 IO 負(fù)載已?分嚴(yán)重,處理部分場景可能收益并不?。于是之后上線了全量的 SharedPreferences 替換來避免此問題發(fā)?。

請注意,這?的“全量”并?真正的全量替換,?是排除了?些可能會受到影響的調(diào)?。?部分都只涉及 業(yè)務(wù),這?不作為核?展開討論;使?“安全的” SharedPreferences 實現(xiàn)只是規(guī)避問題,其根本還 是需要降低系統(tǒng)負(fù)載。

處理全量 SharedPreferences 替換的處理的?法與?志輸出的流程類似。也采?了 MtAjx ?案來攔 截 SharedPreferences 的創(chuàng)建,并返回?個安全的實現(xiàn)。

此處為了容災(zāi),線上做了在線開關(guān)作為全量替換的整體控制策略來規(guī)避未知?險。

最終,這個策略上線之后,上述問題整體降低了 60%-70%,詳見下圖:

3. 首頁創(chuàng)建問題處理

這個問題是通過前?提到的慢函數(shù)數(shù)據(jù)分析發(fā)現(xiàn)的。經(jīng)過堆棧類聚分析之后,關(guān)聯(lián)到了線上的兩個指 標(biāo):

  • 慢函數(shù)——關(guān)聯(lián)了四個問題。
  • ANR——關(guān)聯(lián)了 N 個問題,?且問題很分散。

其中,慢函數(shù)問題多發(fā)?在某些 View 的初始化過程中。下?是?些線上觸發(fā)此問題的點:

  • ViewPagerFix.()
  • MainTabItemLayout.()
  • MainActivity.onCreate()
  • HomeTopHeaderLayout.

篩選出上述問題的最終調(diào)?棧如下:

所有的卡頓點都落在 Runtime.loadLibrary0() 這個調(diào)?上。

線上 ANR 或者慢函數(shù)的數(shù)據(jù)表現(xiàn)也近乎?致:都是?通機(jī)型、低端機(jī)較多。

經(jīng)過分析得知,?通機(jī)型存在?個 BoostFramework 組件?于加快應(yīng)?的響應(yīng)速度:類似的機(jī)制 可以在 特定情況下提升調(diào)度優(yōu)先級、CPU 頻率,從?加快應(yīng)?的響應(yīng)速度。

但在某些情況下,這種機(jī)制會導(dǎo)致應(yīng)?發(fā)?卡頓:BoostFramework 初始化依賴?個 so 的加載。?Runtime.loadlibrary0 是?個 synchronize 修飾的函數(shù),多線程調(diào)?必然會存在鎖競爭情況。

美圖秀秀在啟動過程中,存在著?量“異步”加載 so 的操作。如果?線程先于主線程進(jìn)? Runtime.loadLibrary0 ?法,拿不到鎖的主線程就會等待?線程釋放鎖之后再繼續(xù)執(zhí)?。也就是說,如果某個?線程中存在著耗時較久的 so 加載?為,就會阻塞主線程的 so 加載。

?前 so 的加載時間還是盲區(qū),?法針對性地去處理這個問題。與之前 SharedPreferences 問題處理的思路?樣:使? MtAjx 攔截 System.loadLibrary() ?法并輸出其耗時,最后得到如下數(shù)據(jù)(部分):

從數(shù)據(jù)上看,某些 so 加載確實消耗了不少時間。要解決此問題,?前初步的?案有:

盡量降低異步 so 加載對主線程 so 加載產(chǎn)?的影響

嘗試 Hack ?通平臺的 BoostFramework,讓其延遲加載或提前加載

列舉出可以執(zhí)?的?案如下:

最終上線的?案:

  • 延遲執(zhí)?異步任務(wù)中的 so 加載
  • ?通平臺的 BoostFramewok 加速在合理的時間啟動

對這種系統(tǒng) Hack,必要的容災(zāi)還是要做。這?與之前的?案?樣,通過在線開關(guān)去決定 BoostFramework 加載時機(jī)。

采?最終?案上線之后,得出了?些線上的數(shù)據(jù):

  • 關(guān)聯(lián) ANR 問題發(fā)?數(shù)降低 50%
  • 低端機(jī)啟動速度提升 13%
  • 低端機(jī) ANR 率降低,最?幅度在 50%

復(fù)盤 2、3 兩個問題,都經(jīng)歷了類似的處理過程:

  • 分析:這?包括對問題的根本原因、原理、發(fā)?場景全鏈路進(jìn)?完整分析
  • 建模:指將問題直觀地“數(shù)據(jù)化”。如SharedPreferences 的讀寫頻次分析、 so 加載中的加載時常數(shù)據(jù)分析、以及線上的慢函數(shù)、ANR 數(shù)據(jù)變化。
  • 預(yù)估:列舉現(xiàn)有?案的優(yōu)劣對?,以及可能產(chǎn)?的影響,容災(zāi)措施等
  • 驗證:最終結(jié)果和預(yù)估時的進(jìn)?對?,是否影響到線上關(guān)聯(lián)問題的核?指標(biāo)。

4. BinderProxy 問題處理

線上 Binder 問題的堆棧表現(xiàn)多種多樣,不過其最終調(diào)?點都是android.os.BinderProxy.transactNative() 方法。

經(jīng)過分析、查閱資料后,初步得出結(jié)論。當(dāng)出現(xiàn)此類問題時,系統(tǒng)或應(yīng)?基本都處于以下這些狀態(tài):

  • Binder 本地資源耗盡
  • 遠(yuǎn)程服務(wù)被頻繁調(diào)?,致使遠(yuǎn)程服務(wù)負(fù)載過?
  • 其他資源耗盡情況

這個問題的處理思路跟前?的?較類似:?先是收集不同場景下的 Binder 調(diào)?數(shù)據(jù),然后針對數(shù)據(jù)進(jìn) ?分析、評估是否存在不合理場景。

不同于之前的例?:Binder 問題最終完全發(fā)?在系統(tǒng)層,?法通過 MtAjx 進(jìn)?攔截。因此,換?種? 式:通過 NativeHook 可以攔截所有的 Binder 調(diào)?,從?獲取到 Binder 調(diào)?運?期的數(shù)據(jù)。此處選 擇了 BinderProxy.transact() 作為攔截點:

仍然采??動化測試來模擬線上?戶的使?情況并輸出?份?志,分析后得到如下數(shù)據(jù)(部分):

數(shù)據(jù)反映出了?系列問題:

  • 頻繁獲取本身 package 信息:如 versionName,versionCode
  • 頻繁獲取設(shè)備信息:如 IMEI,IMSI,?卡地址
  • 頻繁?絡(luò)類型檢測,?絡(luò)狀態(tài)檢測
  • 頻繁訪問本地?錄
  • 頻繁權(quán)限檢測

這些?法的調(diào)?頻率都出現(xiàn)了異常(有些甚?超過了 View 繪制)。通過匯總整理,輸出?份最終修改結(jié)論和建議,供內(nèi)部或者第三?去修改問題:

以上這些問題經(jīng)過處理,整體 ANR 問題的發(fā)?都有?定程度地降低。所以,?部分 ANR 問題并?單體問題,通常降低整個應(yīng)?的負(fù)載亦可降低整體 ANR 問題的發(fā)?率。

復(fù)盤思考

經(jīng)過?整?的問題處理之后,通過復(fù)盤得出以下?系列思考。

1. 風(fēng)險控制

在?險存在的時候,通常有以下?種做法:

本地容災(zāi)策略

異常發(fā)?的時候,?適應(yīng)去熔斷某些功能并上報。這個途徑?論從效率還是從?戶體驗上來講,都是最 好的。不過本地化意味著通常需要各種規(guī)則,各種條件去約束。所以?部分情況下這并不是最好的選擇。

在線開關(guān)控制

在觀測到異常數(shù)量上升(?為、報警)之后,通過在線開關(guān)關(guān)閉相應(yīng)的功能。?前最常?的?法,在? 部分場景下都能適?。

熱修復(fù)補丁

在觀測到線上異常之后,通過下發(fā)熱修復(fù)補丁來避免問題的擴(kuò)?。不過部分設(shè)備、渠道可能會失效。

發(fā)布緊急版本

迫不得已情況下使?的下策:緊急版本?論從修復(fù)效率還是從?戶體驗來講,都是?較糟糕的選擇。

2. 保持?jǐn)?shù)據(jù)的準(zhǔn)確 & 完整

完善的基礎(chǔ)數(shù)據(jù)建設(shè)更有助于發(fā)現(xiàn)問題

筆者之前接?公司另?個業(yè)務(wù)的性能優(yōu)化需求時,發(fā)現(xiàn)該業(yè)務(wù)線的應(yīng)?并沒有采集線上 ANR 指標(biāo),這部分在當(dāng)時來看完全屬于盲區(qū),并且根本?法評估有多少?戶流失與此關(guān)聯(lián)。

單?維度的數(shù)據(jù),只能反映部分事實,能互相佐證的多維度的數(shù)據(jù)才更可信

?如性能問題中:ANR 數(shù)據(jù)、慢函數(shù)數(shù)據(jù)、甚?于啟動時?都能相互印證。

3. 別忽視了“蟻穴”

小問題積累到爆發(fā)再填坑,往往會耗費更多的精?。

之前公司內(nèi)部的 AOP 處理?直使? AspectJ ,前期遇到的問題始終在通過加各種規(guī)則去規(guī)避。在后期問題爆發(fā)的時刻,?開發(fā)?套 AOP ?案耗費的??會更多。

沒有外?約束下,?個穩(wěn)定的系統(tǒng)會逐漸地熵增,從?陷?混亂狀態(tài),代碼也是?樣。

質(zhì)量差的代碼不僅會拖慢研發(fā)效率,?且會增加各種各樣的穩(wěn)定性隱患。平時不注意的細(xì)節(jié)會在上百萬、上千萬的?戶?前成倍放?。?如主線程的?次 IO 操作:很多?都覺得“? Kb 的數(shù)據(jù)?已,沒什么?不了的”,可事實真的是這樣嗎?

未來探索

?論過去、現(xiàn)在還是未來, ANR 問題的處理始終是?項具有挑戰(zhàn)的任務(wù)。依靠過去的經(jīng)驗可以避免?些常見的問題,但是面向未來,還需要探索更多的?式去定位和解決問題。

1. 自研性能監(jiān)控平臺

發(fā)現(xiàn)、預(yù)警,到 Bug 跟進(jìn),可以將整個開發(fā)和交付流程串聯(lián)起來。這將是未來性能優(yōu)化?作的??利器。

2. 抽樣上報的詳細(xì) ANR?志

通過對? Bugly 和 XCrash 上報的 ANR ?志,可以看出 XCrash 上報的信息更適合開發(fā)同學(xué)進(jìn)?問題定位。在后期,我們將 XCrash 接?作為?個抽樣的上報?案以補充 ANR 數(shù)據(jù),為定位問題提供更有價值的信息。

3. 業(yè)務(wù)異常關(guān)聯(lián)數(shù)據(jù)分析

通過對核?業(yè)務(wù)的操作路徑和線上的異常數(shù)據(jù)關(guān)聯(lián),可以發(fā)現(xiàn)?些平時容易被忽略的問題定位?法。我們關(guān)聯(lián)了圖?處理的業(yè)務(wù)與 ANR 或 Crash 的發(fā)?時間節(jié)點,來定位 ANR 或 Crash 是否與某個業(yè)務(wù)組件相關(guān)聯(lián)。

結(jié)語

ANR 問題并?單體問題。?部分 ANR 問題只是結(jié)果,其中的誘因千奇百怪,?中所述僅只是冰???。后續(xù)團(tuán)隊還需要不斷地去解決新的問題,并持續(xù)地將已處理問題歸納、總結(jié)、規(guī)范,進(jìn)而才能推?使?,更好地治理 ANR 問題。

注:

?中描述的 MtAjx 暫未公開,如有需要可使? AspectJ 代替

?中?量的經(jīng)驗來源于前?貢獻(xiàn);?平有限難免存在紕漏 -- 如有問題歡迎隨時與我交流:i@zhan gyanwei.com

專家介紹

作者張彥偉,美圖秀秀 Android 專家。2019 年加入美圖,現(xiàn)負(fù)責(zé)美圖秀秀 Android 端優(yōu)化工作。美圖秀秀是 2008 年 10 月 8 日由廈門美圖科技有限公司研發(fā)、推出的一款免費影像處理軟件,全球累計超 10 億用戶,在影像類應(yīng)用排行上長期保持領(lǐng)先優(yōu)勢。

責(zé)任編輯:薛彥澤 來源: 51CTO
相關(guān)推薦

2022-05-02 08:30:46

網(wǎng)絡(luò)Wi-Fi

2014-08-27 10:24:16

APP

2013-04-19 10:17:57

波士頓馬拉松爆炸的大數(shù)據(jù)大數(shù)據(jù)全球技術(shù)峰會

2011-11-21 09:26:32

2011-05-30 14:36:06

Android 在線開發(fā) App Invent

2017-01-12 15:06:30

AndroidAppActivityMan

2019-12-27 14:00:43

傳統(tǒng)IT商業(yè)模式

2018-11-03 16:29:48

Red HatKDE桌面環(huán)境

2013-03-07 11:33:46

App移動應(yīng)用盈利

2012-12-25 11:54:44

App Store兒童保護(hù)隱私

2013-08-13 17:33:17

阿里巴巴BAT

2014-12-15 16:27:54

App推廣

2022-12-26 09:00:07

2024-02-26 00:00:00

RAGGeminiLLM

2021-05-29 10:32:15

XDRSIEM安全

2018-02-25 12:14:20

MITAI技術(shù)卡頓

2020-04-03 21:47:58

網(wǎng)絡(luò)安全 數(shù)據(jù)物聯(lián)網(wǎng)

2015-01-13 11:17:17

2017-01-12 14:21:25

AndroidFragmentActFragment

2013-08-07 10:19:11

Windows phoWP應(yīng)用開發(fā)套件StuWindows Pho
點贊
收藏

51CTO技術(shù)棧公眾號