當前位置: 妍妍網 > 碼農

面試官:Spring Boot 中的監視器是什麽?不是監聽器嘛。。。

2024-04-23碼農

嗨,你好呀,我是哪咤。

面試的時候,被問到 「Spring Boot 中的監視器是什麽?有哪些功能和作用?」

我的第一反應就是, 不應該是監聽器和攔截器嗎?

監聽器 是基於 觀察者模式 的實作,其工作原理是透過註冊監聽器來訂閱特定的事件,當這些事件發生時,Spring框架會通知所有註冊了對應事件的監聽器,然後監聽器會執行相應的操作。

比如初始化數據、讀取配置檔、記錄日誌等。

具體的操作步驟:

  1. 定義一個事件類,它需要繼承自ApplicationEvent;

  2. 建立一個監聽器類,實作ApplicationListener介面,並指定監聽的事件型別;

  3. 在監聽器類中,可以重寫onApplicationEvent方法來定義當事件發生時的具體行為;

  4. 將監聽器註冊到Spring上下文中,這可以透過實作CommandLineRunner介面或者使用@EventListener註解來完成。

面試官:我說的是監視器。

很多小夥伴開發多年,確實是沒註意過監視器這個概念。

Spring Boot中的監視器是Actuator,我一般用來監控響應時間、CPU使用率、記憶體使用情況。

還可以透過分析日誌資訊,快速定位問題原因,還可以提供預警機制,以便在出現故障或異常時及時采取措施進行修復。

監視器可以與自動化運維工具整合,實作自動化部署、監控、報警和恢復等功能,提高運維效率。

可以透過一些端點進行監控和管理,比如:

  1. 透過/actuator/health端點可以檢視套用的健康狀態資訊。

  2. 透過/actuator/info端點獲取套用的基本資訊。

  3. 透過/actuator/metrics端點收集套用執行時的效能指標。

  4. 透過/actuator/httptrace端點追蹤HTTP請求的處理過程。

  5. 記錄套用的使用情況,如存取次數等。

  6. 檢視和管理套用中Spring Bean的狀態。

  7. 允許透過/actuator/shutdown端點來平滑關閉套用。

小結一下:

用於響 應應用程式中的特定事件, 當某個事件發生時,監 器可以 執行預定義的動作。

用於響應特定的套用事件,如服務啟動、請求處理等,以及實作特定業務邏輯的處理。

監視器 指的是能夠監控和管理應用程式狀態的元件或工具。在Spring Boot中,Actuator是一個內建的監控元件,它提供了多種端點來檢查套用的健康狀況、效能指標、日誌資訊等。

監視器 用於監控應用程式的執行狀態,提供健康檢查、效能統計等資訊,幫助維護和最佳化套用效能。

再分享幾道,徹底掌握監視器的常見問題。

1、使用監視器時的有哪些需要註意?

在開始使用監視器之前,需要 明確監控的目標和範圍 。確定需要監控的關鍵指標,如響應時間、錯誤率、資源利用率等,並設定合理的閾值。

根據監控目標, 配置合適的監控策略 。這可能包括監控頻率、數據聚合方式、報警觸發條件等。確保監控策略能夠有效地捕捉到潛在問題,並及時發出警報。

監視器本身也會占用一定的系統資源,並可能對應用程式的效能產生一定影響。因此,在選擇和使用監視器時,需要 權衡其功能和效能開銷 ,確保不會對應用程式造成過大的負擔。

監視器可能會收集到一些敏感資訊,如使用者數據、系統設定等。因此,在使用監視器時,需要 確保敏感資訊得到妥善保護 ,避免泄露給未經授權的人員。

2、除了基本認證,Spring Boot Actuator還支持哪些身份驗證方式?

  • OAuth2 :這是一種開放標準,它允許應用程式在獲得使用者授權後,存取其數據而無需知道使用者的憑據。Actuator可以透過配置OAuth2客戶端和提供授權伺服器的URL來整合OAuth2認證。

  • LDAP(輕量級目錄存取協定) :如果你的應用程式已經使用了LDAP進行使用者管理,Actuator可以配置為使用LDAP進行身份驗證,這樣使用者就可以使用他們在LDAP中的憑據來存取Actuator端點。

  • JWT(JSON Web令牌) :這是一種自包含的令牌,用於在各方之間安全地傳輸資訊。Actuator可以配置為接受JWT作為有效的身份驗證方法。

  • JMX(Java管理擴充套件) :雖然JMX主要用於內部監控和管理,但Actuator也提供了透過JMX端點存取資訊的機制。這通常在開發和測試環境中使用,因為它需要直接連線到執行中的套用。

  • SSH(安全外殼協定) :Actuator支持透過SSH進行遠端存取和管理,這在需要安全的遠端存取時非常有用。

  • 3、Spring Boot中如何使用Actuator?

    (1)在pom.xml檔中添加Actuator的依賴

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    (2)在application.properties或application.yml中配置Actuator的相關內容,例如開啟所有的端點:

    management:
    endpoints:
    web:
    exposure:
    include: "*"

    (3)使用瀏覽器或者命令列工具(如curl)存取不同的端點

    # 獲取套用的健康狀態資訊
    curl http://localhost:8080/actuator/health
    # 獲取套用的基本資訊
    curl http://localhost:8080/actuator/info
    # 獲取套用的效能指標
    curl http://localhost:8080/actuator/metrics
    # 追蹤HTTP請求的處理過程
    curl http://localhost:8080/actuator/httptrace
    # 關閉套用
    curl -X POST http://localhost:8080/actuator/shutdown


    4、如何在Spring Boot Actuator中使用自訂的使用者名稱和密碼進行認證?

    (1)建立一個安全配置類,繼承WebSecurityConfigurerAdapter,並重寫configure(AuthenticationManagerBuilder auth)方法。在該方法中,可以配置自訂的使用者名稱和密碼。

    @Configuration
    @EnableWebSecurity
    public classSecurityConfigextendsWebSecurityConfigurerAdapter{
    @Override
    protectedvoidconfigure(AuthenticationManagerBuilder auth)throws Exception {
    auth.inMemoryAuthentication() // 使用記憶體中的使用者資訊進行認證
    .withUser("myuser"// 自訂使用者名稱
    .password("{noop}mypassword"// 自訂密碼(使用明文)
    .roles("USER"); // 設定使用者角色
    }
    }

    (2)在application.properties或application.yml中配置端點的安全路徑和存取許可權

    management:
    endpoints:
    web:
    base-path:/actuator# 設定Actuator端點的根路徑
    exposure:
    include:"*"# 暴露所有端點
    security:
    enabled:true# 啟用Actuator的安全認證

    (3)啟動套用後,存取Actuator端點時,會提示輸入自訂的使用者名稱和密碼進行身份驗證。例如,存取/actuator/health端點時,瀏覽器會彈出一個登入視窗,要求輸入自訂的使用者名稱和密碼。

    4、如何在Spring Boot Actuator中限制特定端點的存取許可權?

    在Spring Boot Actuator中,可以透過配置端點的存取許可權來限制特定端點的存取。

    (1)建立一個安全配置類,繼承WebSecurityConfigurerAdapter,並重寫configure(HttpSecurity http)方法。在該方法中,可以配置特定端點的存取許可權。

    @Configuration
    @EnableWebSecurity
    public classSecurityConfigextendsWebSecurityConfigurerAdapter{
    @Override
    protectedvoidconfigure(HttpSecurity http)throws Exception {
    http
    .authorizeRequests()
    .antMatchers("/actuator/health").hasRole("ADMIN"// 僅允許具有ADMIN角色的使用者存取/actuator/health端點
    .and()
    .httpBasic(); // 使用基本認證方式
    }
    }

    (2)在application.properties或application.yml中配置使用者名稱和密碼以及使用者的角色:

    spring:
    security:
    user:
    name:admin# 使用者名稱
    password:secret# 密碼
    roles:ADMIN# 使用者角色

    (3)啟動套用後,存取Actuator端點時,會提示輸入使用者名稱和密碼進行身份驗證。例如,存取/actuator/health端點時,瀏覽器會彈出一個登入視窗,要求輸入使用者名稱和密碼。只有具有ADMIN角色的使用者才能成功存取該端點。

    6、如何在Spring Boot Actuator中使用OAuth2進行認證?

    (1)添加spring-boot-starter-oauth2-client依賴到pom.xml檔中

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>

    (2)建立一個安全配置類,繼承WebSecurityConfigurerAdapter,並重寫configure(HttpSecurity http)方法。在該方法中,可以配置端點的存取許可權和OAuth2認證。

    @Configuration
    @EnableWebSecurity
    public classSecurityConfigextendsWebSecurityConfigurerAdapter{
    @Override
    protectedvoidconfigure(HttpSecurity http)throws Exception {
    http.authorizeRequests()
    .antMatchers("/actuator/**").authenticated() // 需要認證才能存取Actuator端點
    .and()
    .oauth2Login(); // 使用OAuth2認證方式
    }
    }

    (3)在application.properties或application.yml中配置OAuth2相關的內容,例如客戶端ID、客戶端金鑰和授權伺服器的URL等。

    spring:
    security:
    oauth2:
    client:
    registration:
    myprovider:# OAuth2提供商名稱
    client-id:your-client-id# 客戶端ID
    client-secret:your-client-secret# 客戶端金鑰
    authorization-grant-type:authorization_code# 授權型別
    redirect-uri:"{baseUrl}/login/oauth2/code/{registrationId}"# 回呼URL
    scope:openid,profile,email# 請求的許可權範圍
    provider:
    myprovider:# OAuth2提供商名稱
    authorization-uri:https://your-authorization-server.com/oauth/authorize# 授權伺服器的授權URL
    token-uri:https://your-authorization-server.com/oauth/token# 授權伺服器的令牌URL
    user-info-uri:https://your-authorization-server.com/userinfo# 使用者資訊URL
    jwk-set-uri:https://your-authorization-server.com/jwks# JSON Web Key Set URL

    (4)啟動套用後,存取Actuator端點時,會跳轉到OAuth2認證伺服器的授權頁面,要求輸入使用者名稱和密碼進行身份驗證。成功認證後,會返回一個授權碼,然後套用會使用該授權碼獲取存取令牌,並進行後續的認證操作。

    7、如何在Spring Boot Actuator中使用JWT進行認證?程式碼舉例說明

    (1)匯入依賴

    首先,需要在計畫的pom.xml檔中添加Spring Security和JWT相關的依賴。

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
    </dependency>

    (2)配置JWT工具類

    建立一個JWT工具類,用於生成和解析JWT令牌。這個工具類應該包含方法來生成令牌(通常在使用者登入時),以及驗證和解析令牌(在需要使用者身份資訊的端點)。

    public classJwtUtil{
    privatestaticfinal String SECRET_KEY = "yourSecretKey"// 替換為你的金鑰
    publicstatic String generateToken(String subject){
    return Jwts.builder()
    .setSubject(subject)
    .setIssuedAt(new Date())
    .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
    .compact();
    }
    publicstatic Claims parseToken(String token){
    return Jwts.parser()
    .setSigningKey(SECRET_KEY)
    .parseClaimsJws(token)
    .getBody();
    }
    }

    (3)建立攔截器

    可以建立一個攔截器來處理帶有JWT的請求。攔截器會檢查每個請求的HTTP頭部是否包含JWT,如果存在,則解析JWT並驗證其有效性。如果驗證成功,請求將被允許繼續;如果驗證失敗,將返回未經授權的響應。

    public classJwtInterceptorimplementsHandlerInterceptor{
    @Override
    publicbooleanpreHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {
    String token = request.getHeader("Authorization");
    if (token != null && !token.isEmpty()) {
    try {
    JwtUtil.parseToken(token); // 驗證令牌
    returntrue// 令牌有效,允許請求繼續
    catch (Exception e) {
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 令牌無效,返回未授權響應
    returnfalse;
    }
    else {
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 缺少令牌,返回未授權響應
    returnfalse;
    }
    }
    }

    (4)安全儲存金鑰

    確保JWT的金鑰安全儲存,並定期更換以防止潛在的安全風險。金鑰的安全性對於維護整個認證系統的安全至關重要。

    (5)使用Actuator端點

    Spring Boot Actuator提供了多種監控和管理生產環境的端點。在使用JWT進行認證時,可以透過配置Actuator的端點來限制存取,只有持有有效JWT的使用者才能存取這些端點。

    (6)測試驗證

    完成以上配置後,應該進行全面的測試,以確保JWT認證機制按預期工作。這包括測試令牌的生成、驗證過程,以及確保未授權的請求被正確拒絕。

    8、JWT是什麽?有什麽用?有哪些套用場景?

    JWT,全稱為JSON Web Token,就是我們經常提到的token,它以JSON物件的形式安全地在各個實體間傳輸資訊。這些資訊是經過數位簽名的,因此可以被驗證和信任。

    JWT由三部份組成,它們用點(.)分隔,分別是:

    1. Header(頭部) :包含兩部份資訊,令牌的型別(即JWT)和所使用的簽名演算法(如HMAC SHA256或RSA)。

    2. Payload(負載) :包含有關實體(通常是使用者)和其他數據的聲明。這部份也可以包含其他自訂資訊。但請註意,JWT預設不加密,任何人都可以解碼其內容,因此不要將敏感資訊放入負載中,除非它們是加密的。

    3. Signature(簽名) :是使用頭部中指定的演算法和金鑰對頭部和負載進行簽名的結果。這使得接收方可以驗證資訊的發送者以及資訊的完整性。

    JWT的主要用途包括:

    1. 授權 :使用者登入後,系統會返回一個JWT,之後的每個請求都會攜帶這個令牌,以便使用者存取允許的資源和服務。這種方式在實作單點登入(SSO)時特別有用,因為JWT可以輕松跨域使用,且相比傳統Cookie方式更加輕量級。

    2. 防止數據篡改 :JWT可以使用加密演算法對數據進行簽名,即使數據在傳輸過程中被截獲,由於缺乏發送方的私鑰,攻擊者很難同時篡改數據和簽名,從而保證了數據的完整性。

    3. 鑒權 :JWT可以用於驗證使用者是否有權存取系統。與傳統的Session加Cookie的組合相比,JWT將使用者數據直接下發給客戶端,每次請求時客戶端會附帶JWT一並行送給伺服器,這樣伺服器就無需緩存使用者數據,降低了伺服器的開銷,並且提高了系統的可延伸性。

    9、在企業套用整合中,JWT有哪些優勢?

    JWT可以在使用者初次登入後發放,之後的每次請求都會攜帶這個令牌,無需再次進行身份驗證,這簡化了認證流程。

    JWT自身包含了所有必要的身份驗證資訊,這意味著伺服器不需要儲存會話資訊,這增加了系統的可用性和伸縮性,減輕了伺服端的負擔。

    JWT基於標準JSON格式,可以輕松在不同的平台和框架之間傳遞和使用,這在微服務架構和分布式系統中尤為重要。

    JWT通常使用HS256等加密演算法進行簽名,確保了令牌的完整性和真實性。

    10、如何在Spring Boot Actuator中使用SSH進行認證?程式碼舉例說明

    (1)匯入依賴

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
    <groupId>com.hierynomus</groupId>
    <artifactId>sshj</artifactId>
    <version>0.31.0</version>
    </dependency>

    (2)在application.properties或application.yml配置檔中,可以設定SSH的認證資訊。

    management:
    endpoints:
    web:
    exposure:
    include:'*'# 暴露所有端點
    endpoint:
    health:
    show-details:always# 顯示健康檢查詳細資訊
    security:
    enabled:true# 啟用安全認證
    roles:admin# 設定存取許可權為admin角色
    ssh:
    username:your_username# SSH使用者名稱
    password:your_password# SSH密碼
    host:your_host# SSH主機名

    (3)在資料庫中建立一個具有管理員角色的使用者,用於存取Actuator端點。這可以透過使用Spring Data JPA和Hibernate來實作。例如,可以建立一個名為User的實體類和一個名為UserRepository的介面:

    @Entity
    public classUser{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    // 省略getter和setter方法
    }
    @Repository
    publicinterfaceUserRepositoryextendsJpaRepository<UserLong{
    Optional<User> findByUsername(String username);
    }

    (4)在Spring Security的配置類中,可以配置SSH的安全認證。例如,可以建立一個名為SecurityConfig的配置類:

    @Configuration
    @EnableWebSecurity
    public classSecurityConfigextendsWebSecurityConfigurerAdapter{
    @Autowired
    private UserRepository userRepository;
    @Override
    protectedvoidconfigure(HttpSecurity http)throws Exception {
    http.authorizeRequests()
    .antMatchers("/actuator/**").hasRole("ADMIN"// 只允許ADMIN角色存取Actuator端點
    .and()
    .formLogin().permitAll() // 允許所有使用者存取登入頁面
    .and()
    .logout().permitAll(); // 允許所有使用者存取登出頁面
    }
    @Autowired
    publicvoidconfigureGlobal(AuthenticationManagerBuilder auth)throws Exception {
    auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());
    }
    @Bean
    public UserDetailsService userDetailsService(){
    return username -> userRepository.findByUsername(username)
    .map(user -> User.withUsername(user.getUsername()).password(user.getPassword()).roles("ADMIN").build())
    .orElseThrow(() -> new UsernameNotFoundException("User not found"));
    }
    }

    完成以上配置後,應該進行全面的測試,以確保SSH認證機制按預期工作。這包括測試SSH連線、登入和登出功能等。

    11、SSH是什麽?有什麽用?有哪些套用場景?

    SSH最初設計用於替代不安全的Telnet和FTP,現在它廣泛套用於安全地連線和管理遠端系統。

    SSH的主要用途包括:

    1. 遠端登入和終端存取 :使用者可以透過SSH客戶端遠端登入到伺服器或其他裝置,並進行命令列操作或圖形界面操作。

    2. 檔傳輸 :SFTP(SSH File Transfer Protocol)是基於SSH實作的安全檔傳輸協定,允許使用者在本地系統和遠端伺服器之間安全地傳輸檔。

    3. 埠轉發 :SSH可以實作埠轉發,從而在本地主機和遠端主機之間建立安全的通訊通道,用於存取遠端主機上的服務。

    4. 遠端執行命令 :SSH允許使用者在遠端伺服器上執行命令,這對於自動化任務和遠端管理非常有用。

    5. 隧道 :SSH可以建立安全的通訊隧道,透過不受信任的網路傳輸數據。

    12、SSH和Telnet的區別是什麽?

    SSH和Telnet都是遠端登入協定,但它們在安全性、加密方式和埠號等方面存在顯著差異。

    1. SSH不僅是替代Telnet的遠端控制台管理應用程式的行業標準,還可以為ftp、pop等提供一個安全的通道。相比之下,Telnet的功能相對單一,主要提供在本地電腦上完成遠端主機工作的能力。

    2. SSH提供了加密傳輸,而Telnet則使用明文傳輸。

    3. SSH通常使用埠22,而Telnet使用埠23

    4. 由於Telnet傳輸的數據是明文的,因此預設情況下防火墻是不信任Telnet的。而SSH由於其加密特性,通常能得到防火墻的信任。

    今天就到這裏啦,明天見~

    謝謝你那麽有耐心,看到了這裏,共勉~

    往期文章: