眾安保險面試難不難,我們一起瞧瞧去!
1.說一下Java內(nèi)存模型?
注意,當(dāng)問到 Java 內(nèi)存模型的時候,不要和 JVM 內(nèi)存布局(JVM 運行時數(shù)據(jù)區(qū)域)搞混了,這塊問的不是 JVM 內(nèi)存的布局是啥,而是 Java 內(nèi)存模型,Java Memory Model,簡稱 JMM。
Java 內(nèi)存模型是用來定義 Java 線程和內(nèi)存之間的操作規(guī)范的,目的是解決多線程正確執(zhí)行的問題。Java 內(nèi)存模型規(guī)范的定義確保了多線程程序的可見性、有序性和原子性,從而保證了線程之間正確的交互和數(shù)據(jù)一致性。Java 內(nèi)存模型主要包括以下內(nèi)容:
- 主內(nèi)存(Main Memory):所有線程共享的內(nèi)存區(qū)域,包含了對象的字段、方法和運行時常量池等數(shù)據(jù)。
- 工作內(nèi)存(Working Memory):每個線程擁有自己的工作內(nèi)存,用于存儲主內(nèi)存中的數(shù)據(jù)的副本。線程只能直接操作工作內(nèi)存中的數(shù)據(jù)。
- 內(nèi)存間交互操作:線程通過讀取和寫入操作與主內(nèi)存進(jìn)行交互。讀操作將數(shù)據(jù)從主內(nèi)存復(fù)制到工作內(nèi)存,寫操作將修改后的數(shù)據(jù)刷新到主內(nèi)存。
- 原子性(Atomicity):JMM 保證基本數(shù)據(jù)類型(如 int、long)的讀寫操作具有原子性,即不會被其他線程干擾,保證操作的完整性。
- 可見性(Visibility):JMM 確保一個線程對共享變量的修改對其他線程可見。這意味著一個線程在工作內(nèi)存中修改了數(shù)據(jù)后,必須將最新的數(shù)據(jù)刷新到主內(nèi)存,以便其他線程可以讀取到更新后的數(shù)據(jù)。
- 有序性(Ordering):JMM 保證程序的執(zhí)行順序按照一定的規(guī)則進(jìn)行,不會出現(xiàn)隨機(jī)的重排序現(xiàn)象。這包括了編譯器重排序、處理器重排序和內(nèi)存重排序等。
Java 內(nèi)存模型通過以上規(guī)則和語義,提供了一種統(tǒng)一的內(nèi)存訪問方式,使得多線程程序的行為可預(yù)測、可理解,并幫助開發(fā)者編寫正確和高效的多線程代碼。開發(fā)者可以利用 JMM 提供的同步機(jī)制(如關(guān)鍵字 volatile、synchronized、Lock 等)來實現(xiàn)線程之間的同步和通信,以確保線程安全和數(shù)據(jù)一致性。
內(nèi)存模型的簡單執(zhí)行示例圖如下:
圖片
2.List、Set、Map的區(qū)別?
List、Set 和 Map 都是常見的集合接口,用于存儲和操作數(shù)據(jù),它們的區(qū)別如下:
- List 是有序的集合,允許重復(fù)元素,可以按索引訪問。它的常見實現(xiàn)類有 ArrayList、LinkedList 和 Vector。
- Set 是無序的集合,不允許重復(fù)元素。它的常見實現(xiàn)類有 HashSet、TreeSet 和 LinkedHashSet。
- Map 是鍵值對的映射集合,鍵不允許重復(fù),值可以重復(fù)。它的常見實現(xiàn)類有 HashMap、TreeMap 和 LinkedHashMap。
3.介紹一下設(shè)計模式?
當(dāng)聊到設(shè)計模式時,可以舉一些常見的設(shè)計模式,以及這些設(shè)計模式的具體應(yīng)用,比如以下這些:
- 工廠模式(Factory Pattern):工廠模式是一種創(chuàng)建型設(shè)計模式,它提供了一種創(chuàng)建對象的方式,使得應(yīng)用程序可以更加靈活和可維護(hù)。比如在 Spring 中,F(xiàn)actoryBean 就是一個工廠模式的實現(xiàn),使用它的工廠模式就可以創(chuàng)建出來其他的 Bean 對象。
- 單例模式(Singleton Pattern):單例模式是一種創(chuàng)建型設(shè)計模式,它保證一個類只有一個實例,并提供了一個全局訪問點。比如在 Spring 中,所以的 Bean 默認(rèn)是單例的,這意味著每個 Bean 只會被創(chuàng)建一次,并且可以在整個應(yīng)用程序中共享。
- 代理模式模式(Proxy Pattern):代理模式是一種結(jié)構(gòu)型設(shè)計模式,它允許開發(fā)人員在不修改原有代碼的情況下,向應(yīng)用程序中添加新的功能。比如在 Spring AOP(面向切面編程)就是使用代理模式的實現(xiàn),它允許開發(fā)人員在方法調(diào)用前后執(zhí)行一些自定義的操作,比如日志記錄、性能監(jiān)控等。
- 模板方法模式(Template Pattern):模板方法模式是最常用的設(shè)計模式之一,它是指定義一個操作算法的骨架,而將一些步驟的實現(xiàn)延遲到子類中去實現(xiàn),使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。此模式是基于繼承的思想實現(xiàn)代碼復(fù)用的。比如在 MyBatis 中的典型代表 BaseExecutor,在 MyBatis 中 BaseExecutor 實現(xiàn)了大部分SQL 執(zhí)行的邏輯。
- 觀察者模式(Observer Pattern):定義了一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都會得到通知并自動更新。比如事件驅(qū)動、消息傳遞等功能時,可以使用觀察者模式,例如 Spring Event 事件機(jī)制。
- 適配器模式(Adapter Pattern):適配器模式是一種結(jié)構(gòu)型設(shè)計模式,它允許開發(fā)人員將一個類的接口轉(zhuǎn)換成另一個類的接口,以滿足客戶端的需求。在 Spring 中,適配器模式常用于將不同類型的對象轉(zhuǎn)換成統(tǒng)一的接口,比如將 Servlet API 轉(zhuǎn)換成 Spring MVC 的控制器接口。
4.MySQL存儲結(jié)構(gòu)?
在 MySQL 默認(rèn)的存儲引擎 InnoDB 中,所有數(shù)據(jù)都被邏輯地存放在一個空間內(nèi),稱為表空間(tablespace),而表空間由段(sengment)、區(qū)(extent)、頁(page)組成。
圖片
其中:
- 表空間(tablespace)是一組邏輯文件,用于存儲表和索引數(shù)據(jù)。它是 InnoDB 存儲引擎的基本組織單位,可以看作是一個獨立的存儲區(qū)域。
- 段(segment)是表空間的子單位,它是邏輯上連續(xù)的數(shù)據(jù)塊,存儲了一組數(shù)據(jù)頁。段可以是用于存儲表數(shù)據(jù)的數(shù)據(jù)段,也可以是用于存儲索引的索引段。
- 區(qū)(extent)是段的子單位,它是一組連續(xù)的物理頁,通常是 64 個連續(xù)的頁。在一個區(qū)中,可以存儲一個或多個數(shù)據(jù)頁。
- 頁(page)是 InnoDB 存儲數(shù)據(jù)的最小單位,通常為 16KB 大小。每個頁都有一個唯一的標(biāo)識符,用于在磁盤和內(nèi)存中定位和管理數(shù)據(jù)。InnoDB 使用頁來存儲表的行數(shù)據(jù)和索引數(shù)據(jù)。
表空間包含多個段,段包含多個區(qū),區(qū)包含多個頁。這種層次結(jié)構(gòu)幫助 InnoDB 有效地管理存儲空間,并提供高性能和可靠性的數(shù)據(jù)訪問。
舉一個例子,假設(shè)表空間就是整個書架,段是書架的每一層,區(qū)是每一層上的每一個格子,頁是每個格子里面放的一頁紙。這種層次結(jié)構(gòu)讓 MySQL InnoDB 能夠更有效地管理和訪問數(shù)據(jù),就像你可以根據(jù)書的編號和位置快速找到你想要的書籍一樣。
5.索引失效的場景?
常見的索引失效場景有以下這些:
- 未遵循最左匹配原則
- 使用列運算
- 使用函數(shù)方法
- 類型轉(zhuǎn)換
- 使用 is not null
- 錯誤的模糊匹配,使用右 % 開始查詢。
具體內(nèi)容請參考:https://www.javacn.site/interview/mysql/indexinvalid.html
6.為什么使用函數(shù)索引會失效?
使用函數(shù)導(dǎo)致索引失效的原因,是因為函數(shù)會對索引列的值進(jìn)行計算或轉(zhuǎn)換,導(dǎo)致 MySQL 無法直接匹配索引中的數(shù)據(jù),從而無法使用索引來進(jìn)行查詢優(yōu)化了。
比如以下索引結(jié)構(gòu):
圖片
如果你的 SQL 語句條件用的是 where t_modified='2018-7-1' 的話,引擎就會按照上面綠色箭頭的路線,快速定位到 t_modified='2018-7-1' 需要的結(jié)果。實際上,B+ 樹提供的這個快速定位能力,來源于同一層兄弟節(jié)點的有序性。
但是,如果計算 month() 函數(shù)的話,你會看到傳入 7 的時候,在樹的第一層就不知道該怎么辦了。
也就是說,對索引字段做函數(shù)操作,可能會破壞索引值的有序性,因此優(yōu)化器就決定放棄走樹搜索功能。
7.Spring事務(wù)有哪兩種?
Spring 提供了兩種事務(wù):
- 編程式事務(wù)
- 聲明式事務(wù)
它們的實現(xiàn)如下。
7.1 編程式事務(wù)
@RestController
public class UserController {
// 事務(wù)管理器
@Resource
private DataSourceTransactionManager dataSourceTransactionManager;
// 定義事務(wù)屬性
@Resource
private TransactionDefinition transactionDefinition;
@Resource
private UserService userService;
@RequestMapping("/sava")
public Object save(User user) {
// 開啟事務(wù)
TransactionStatus transactionStatus = dataSourceTransactionManager
.getTransaction(transactionDefinition);
// 插入數(shù)據(jù)庫
int result = userService.save(user);
// 提交事務(wù)
dataSourceTransactionManager.commit(transactionStatus);
// // 回滾事務(wù)
// dataSourceTransactionManager.rollback(transactionStatus);
return result;
}
}
7.2 聲明式事務(wù)
聲明式事務(wù)的實現(xiàn)非常簡單,只需要給類或方法上添加 @Transactional 注解即可,如下代碼所示:
@RequestMapping("/save")
@Transactional // 添加此注解就是聲明式事務(wù)
public Object save(User user) {
int result = userService.save(user);
return result;
}
8.@Transactional實現(xiàn)原理?
@Transactional 注解的實現(xiàn)原理是基于 Spring AOP,Spring AOP 又是基于動態(tài)代理(模式)的實現(xiàn)。
在 Spring 中,@Transactional 注解會通過 AOP 機(jī)制生成一個代理 connection 對象,并將其放入 DataSource 實例的某個與 DataSourceTransactionManager 相關(guān)的某處容器中。這樣,當(dāng)開始執(zhí)行目標(biāo)方法之前先開啟事務(wù),如果方法正常執(zhí)行完成則提交事務(wù),如果執(zhí)行中出現(xiàn)了異常,則會回滾事務(wù)。
9.事務(wù)如何合并@Transactional修飾的方法?
當(dāng)一個被 @Transactional 修飾的方法調(diào)用另一個被 @Transactional 修飾的方法時,事務(wù)會通過事務(wù)的傳播機(jī)制,也就是 Propagation 屬性的設(shè)置來合并事務(wù),事務(wù)傳播機(jī)制總共有以下 7 種:
- Propagation.REQUIRED:默認(rèn)的事務(wù)傳播級別,它表示如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù)。
- Propagation.SUPPORTS:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運行。
- Propagation.MANDATORY:(mandatory:強(qiáng)制性)如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常。
- Propagation.REQUIRES_NEW:表示創(chuàng)建一個新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。也就是說不管外部方法是否開啟事務(wù),Propagation.REQUIRES_NEW 修飾的內(nèi)部方法會新開啟自己的事務(wù),且開啟的事務(wù)相互獨立,互不干擾。
- Propagation.NOT_SUPPORTED:以非事務(wù)方式運行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
- Propagation.NEVER:以非事務(wù)方式運行,如果當(dāng)前存在事務(wù),則拋出異常。
- Propagation.NESTED:如果當(dāng)前存在事務(wù),則創(chuàng)建一個事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運行;如果當(dāng)前沒有事務(wù),則該取值等價于 PROPAGATION_REQUIRED。
所以,當(dāng)你不設(shè)置 @Transactional 的 Propagation 屬性時也會合并事務(wù)。
而事務(wù)的傳播機(jī)制 REQUIRED 合并事務(wù)是通過事務(wù)同步器(TransactionSynchronization)和事務(wù)管理器(TransactionManager)來完成的。
- 事務(wù)同步器(TransactionSynchronization):事務(wù)同步器是一個接口,定義了在事務(wù)生命周期中的各個階段執(zhí)行的回調(diào)方法。它包括事務(wù)開始前、事務(wù)提交/回滾后以及事務(wù)完成后等方法。事務(wù)同步器允許注冊和執(zhí)行事務(wù)相關(guān)的操作,如預(yù)提交、后提交、回滾等。
- 事務(wù)管理器(TransactionManager):事務(wù)管理器是 Spring 框架中用于管理事務(wù)的核心接口。它負(fù)責(zé)控制事務(wù)的開始、提交或回滾,并提供事務(wù)的隔離級別和超時等屬性的管理。事務(wù)管理器與底層的數(shù)據(jù)訪問技術(shù)(如JDBC、Hibernate、JPA等)進(jìn)行交互,確保數(shù)據(jù)操作與事務(wù)的一致性。
基于以上概念,REQUIRED 事務(wù)傳播機(jī)制的實現(xiàn)步驟如下:
- 當(dāng)一個帶有 @Transactional(propagation = Propagation.REQUIRED) 注解的方法被調(diào)用時,Spring 會檢查當(dāng)前是否存在一個活動的事務(wù)。
- 如果當(dāng)前存在一個事務(wù),被調(diào)用方法會加入該事務(wù),并與調(diào)用方法共享同一個事務(wù)。Spring 通過事務(wù)同步器(TransactionSynchronization)將被調(diào)用方法注冊為事務(wù)的一部分。
- 如果當(dāng)前不存在事務(wù),事務(wù)管理器(TransactionManager)會創(chuàng)建一個新的事務(wù),并將其與被調(diào)用方法關(guān)聯(lián)起來。被調(diào)用方法成為這個新事務(wù)的第一個參與者。
- 在事務(wù)執(zhí)行過程中,如果被調(diào)用方法拋出異常,則整個事務(wù)將被標(biāo)記為回滾,并觸發(fā)事務(wù)回滾操作。
- 在事務(wù)執(zhí)行完成后,事務(wù)管理器負(fù)責(zé)提交整個事務(wù),并觸發(fā)事務(wù)提交操作。
- 在事務(wù)提交或回滾后,事務(wù)同步器會調(diào)用事務(wù)完成的回調(diào)方法,執(zhí)行相應(yīng)的清理工作。
通過以上步驟,REQUIRED 事務(wù)傳播機(jī)制實現(xiàn)了被調(diào)用方法與調(diào)用方法共享或創(chuàng)建新的事務(wù),并保證在事務(wù)執(zhí)行過程中的一致性和隔離性。
10.Redis數(shù)據(jù)類型有哪些?
Redis 常用的數(shù)據(jù)類型有 5 種:String 字符串類型、List 列表類型、Hash 哈希表類型、Set 集合類型、Sorted Set 有序集合類型,如下圖所示: 這 5 種常用類型的用途如下:
- String:字符串類型,常見使用場景是:存儲 Session 信息、存儲緩存信息(如詳情頁的緩存)、存儲整數(shù)信息,可使用 incr 實現(xiàn)整數(shù)+1,和使用 decr 實現(xiàn)整數(shù) -1;
- List:列表類型,常見使用場景是:實現(xiàn)簡單的消息隊列、存儲某項列表數(shù)據(jù);
- Hash:哈希表類型,常見使用場景是:存儲 Session 信息、存儲商品的購物車,購物車非常適合用哈希字典表示,使用人員唯一編號作為字典的 key,value 值可以存儲商品的 id 和數(shù)量等信息、存儲詳情頁信息;
- Set:集合類型,是一個無序并唯一的鍵值集合,它的常見使用場景是:關(guān)注功能,比如關(guān)注我的人和我關(guān)注的人,使用集合存儲,可以保證人員不會重復(fù);
- Sorted Set:有序集合類型,相比于 Set 集合類型多了一個排序?qū)傩?score(分值),它的常見使用場景是:可以用來存儲排名信息、關(guān)注列表功能,這樣就可以根據(jù)關(guān)注實現(xiàn)排序展示了。
更多詳情請參考:https://www.javacn.site/interview/redis/types.html
11.Redis如何實現(xiàn)分布式鎖?
Redis 作為一個獨立的三方系統(tǒng)(通常被作為緩存中間件使用),其天生的優(yōu)勢就是可以作為一個分布式系統(tǒng)(分布式鎖)來使用,如下圖所示:在 Redis 中實現(xiàn)分布式鎖可以使用 SETNX 和 EXPIRE 命令來實現(xiàn),SETNX 是 "SET if Not eXists" 的縮寫,是一個原子性操作,用于在指定的 key 不存在時設(shè)置 key 的值。如果 key 已經(jīng)存在,SETNX 操作將不做任何事情,返回失??;如果 key 不存在,SETNX 操作會設(shè)置 key 的值,并返回成功。而 EXPIRE 是設(shè)置鎖的過期時間的,主要為了防止死鎖的發(fā)生,SETNX + EXPIRE 的實現(xiàn)命令如下:
圖片
其中“nx”表示 not exists 不存在則設(shè)置 key,“ex 10”表示過期時間為 10 秒,“mylock”值為 key,“l(fā)ock”值為 value。更多詳情請參考:https://www.javacn.site/interview/redis/redis_lock.html
12.什么時候用RocketMQ?
RocketMQ 是一個分布式消息中間件系統(tǒng),主要用于解決高吞吐量、低延遲的消息傳遞需求。以下是一些 RocketMQ 的使用場景:
- 異步消息傳遞:RocketMQ 提供了可靠的異步消息傳遞機(jī)制,可以在分布式系統(tǒng)中實現(xiàn)解耦和異步處理。例如,在電商平臺中,當(dāng)用戶下單成功后,可以使用 RocketMQ 異步地發(fā)送訂單信息給庫存系統(tǒng)和支付系統(tǒng),以提高系統(tǒng)的響應(yīng)速度和可靠性。
- 流式數(shù)據(jù)處理:RocketMQ 支持高吞吐量的消息傳遞,適用于大規(guī)模的實時數(shù)據(jù)處理場景。例如,日志收集和分析系統(tǒng)可以使用 RocketMQ 作為消息中間件,將分布式系統(tǒng)產(chǎn)生的日志實時傳遞給日志處理系統(tǒng),進(jìn)行實時監(jiān)控和分析。
- 事件驅(qū)動架構(gòu):RocketMQ 可以作為事件驅(qū)動架構(gòu)的基礎(chǔ)設(shè)施,實現(xiàn)系統(tǒng)間的事件通知和響應(yīng)。例如,微服務(wù)架構(gòu)中的各個服務(wù)可以通過 RocketMQ 發(fā)送事件消息來通知其他服務(wù)進(jìn)行相應(yīng)的操作,實現(xiàn)解耦和靈活的系統(tǒng)架構(gòu)。
- 分布式事務(wù)消息:RocketMQ 提供了事務(wù)消息的支持,可以確保分布式系統(tǒng)中的消息發(fā)送和業(yè)務(wù)操作的原子性。在分布式事務(wù)場景下,可以使用 RocketMQ 發(fā)送事務(wù)消息,以確保消息的可靠傳遞和業(yè)務(wù)操作的一致性。
- 流量削峰與消息堆積:RocketMQ 支持消息的異步發(fā)送和批量發(fā)送,可以用于平滑處理系統(tǒng)的流量峰值和消息的堆積情況。例如,在雙11等促銷活動中,可以使用 RocketMQ 來處理大量的訂單請求,避免系統(tǒng)過載和消息丟失。
所以,RocketMQ 在高吞吐量、低延遲、可靠性和擴(kuò)展性等方面具備優(yōu)勢,適用于許多分布式系統(tǒng)和大規(guī)模數(shù)據(jù)處理場景。
13.說下RocketMQ和OpenFeign的應(yīng)用場景?
RocketMQ 應(yīng)用場景上個問題已經(jīng)說了。
OpenFeign 的全稱是 Spring Cloud OpenFeign,它是 Spring 官方推出的一種聲明式服務(wù)調(diào)用和負(fù)載均衡組件。它的出現(xiàn)就是為了替代已經(jīng)進(jìn)入停更維護(hù)狀態(tài)的 Feign(Netflix Feign)的。也就是說 OpenFeign(Spring Cloud OpenFeign)是 Feign 的升級版,因為 Feign 停更維護(hù)了,所以 Spring 官方需要推出了一個新的新的框架來對 Feign 功能進(jìn)行升級和擴(kuò)展。
OpenFeign 應(yīng)用場景:
- 微服務(wù)架構(gòu):OpenFeign 可以在微服務(wù)架構(gòu)中作為服務(wù)之間進(jìn)行通信的客戶端工具。它通過定義接口和注解的方式,使得服務(wù)之間的通信變得簡單明了。開發(fā)人員只需要定義接口,而無需關(guān)注底層的 HTTP 請求和響應(yīng)處理,從而提高開發(fā)效率。
- 客戶端負(fù)載均衡:OpenFeign 集成了負(fù)載均衡功能,可以與負(fù)載均衡器(如 Ribbon)一起使用,實現(xiàn)客戶端負(fù)載均衡。通過配置合適的負(fù)載均衡策略,可以將請求分發(fā)到多個服務(wù)實例上,提高系統(tǒng)的可用性和吞吐量。
- 服務(wù)降級與容錯:OpenFeign 可以集成斷路器(如 Hystrix)來實現(xiàn)服務(wù)的降級和容錯處理。當(dāng)服務(wù)不可用或出現(xiàn)異常時,可以定義降級策略,返回預(yù)設(shè)的響應(yīng),以防止故障在整個系統(tǒng)中擴(kuò)散。
OpenFeign 具體使用可參考:https://juejin.cn/post/7101545210315800612
14.抽象類和接口的區(qū)別?
在 Java 中,抽象類和接口是兩種不同的類類型。它們都不能直接實例化,并且它們都是用來定義一些基本的屬性和方法的,但它們有以下幾點不同:
- 定義不同:定義的關(guān)鍵字不同,抽象類是 abstract,而接口是 interface。
- 方法實現(xiàn):抽象類可以包含抽象方法和具體方法,而接口只能包含方法聲明(抽象方法)。
- 方法訪問控制符不同:抽象類無限制,只是抽象類中的抽象方法不能被 private 修飾;而接口有限制,接口默認(rèn)的是 public 控制符。
- 實現(xiàn)/繼承數(shù)量不同:一個類只能繼承一個抽象類,但可以實現(xiàn)多個接口。
- 包含變量不同:抽象類可以包含實例變量和靜態(tài)變量,而接口只能包含常量。
- 構(gòu)造函數(shù)不同:抽象類可以有構(gòu)造函數(shù),而接口不能有構(gòu)造函數(shù)。
更多內(nèi)容請參考:https://www.javacn.site/interview/basic/abstract-interface.html
15.什么時候用抽象類?什么時候用接口?
接口是用來定義規(guī)范的,而抽象類提供了代碼重用。所以,當(dāng)你要定義規(guī)范時可以使用接口,當(dāng)你要重用代碼時可以使用抽象類。
16.try、catch、finally各有return,會怎么執(zhí)行?
程序最終會返回 finally 中的 return 值。
因為在 finally 塊中使用了 return 語句,它將會覆蓋在之前的 try 塊或 catch 塊中的返回值。
17.服務(wù)宕機(jī)時直接降級是最優(yōu)解嗎?
服務(wù)降級以及服務(wù)熔斷和服務(wù)限流都不是最優(yōu)解,因為以上所有操作都是以犧牲用戶體驗為前提的,而最優(yōu)的解決方案,應(yīng)該是讓用戶不受影響,讓用戶無感知的使用程序才對。
所以我們可以使用負(fù)載均衡與集群化,將服務(wù)部署在多臺服務(wù)器上,通過負(fù)載均衡來分發(fā)請求,當(dāng)其中一臺服務(wù)宕機(jī)時,負(fù)載均衡可以自動將請求轉(zhuǎn)發(fā)給其他正常運行的服務(wù),通過集群化部署,可以提高系統(tǒng)的可靠性和可用性,讓用戶無感知才是最優(yōu)解。
參考 & 鳴謝
冰河的博客
blog.csdn.net/MariaOzawa/article/details/107363136