最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot利用Undertow實現(xiàn)高可用的反向代理配置

 更新時間:2025年06月30日 08:26:24   作者:風(fēng)象南  
Undertow是一個采用Java開發(fā)的靈活的高性能Web服務(wù)器,本文將介紹如何利用?Undertow?服務(wù)器的反向代理能力,實現(xiàn)高可用的反向代理配置,感興趣的可以了解下

引言

在微服務(wù)架構(gòu)中,反向代理是一個不可或缺的組件,它負(fù)責(zé)請求轉(zhuǎn)發(fā)、負(fù)載均衡、安全過濾等關(guān)鍵功能。

通常我們會選擇 Nginx、HAProxy 等專業(yè)反向代理組件,但在某些場景下,使用 Spring Boot 內(nèi)置的反向代理功能可以簡化架構(gòu),減少運維復(fù)雜度。

本文將介紹如何利用 Undertow 服務(wù)器的反向代理能力,實現(xiàn)高可用的反向代理配置。

Undertow 簡介

Undertow 是一個采用 Java 開發(fā)的靈活的高性能 Web 服務(wù)器,提供基于 NIO 的阻塞和非阻塞 API。

作為 Spring Boot 支持的內(nèi)嵌式服務(wù)器之一,它具有以下特點:

  • 輕量級:核心僅依賴于 JBoss Logging 和 xnio
  • 高性能:在多核系統(tǒng)上表現(xiàn)優(yōu)異
  • 內(nèi)置反向代理:支持 HTTP、HTTPS、HTTP/2 代理
  • 可擴展:通過 Handler 鏈模式支持靈活擴展

為什么選擇 Undertow 內(nèi)置反向代理

在某些場景下,使用 Undertow 內(nèi)置的反向代理功能比獨立部署 Nginx 等代理服務(wù)器更有優(yōu)勢:

1. 簡化架構(gòu):減少額外組件,降低部署復(fù)雜度

2. 統(tǒng)一技術(shù)棧:全 Java 技術(shù)棧,便于開發(fā)團隊維護

3. 配置靈活:可通過代碼動態(tài)調(diào)整代理規(guī)則

4. 節(jié)約資源:適合資源有限的環(huán)境,如邊緣計算場景

5. 集成監(jiān)控:與 Spring Boot 的監(jiān)控體系無縫集成

基礎(chǔ)配置

步驟 1:添加 Undertow 依賴

首先,確保 Spring Boot 項目使用 Undertow 作為嵌入式服務(wù)器:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.5</version>
        <relativePath/>
    </parent>
    <groupId>demo</groupId>
    <artifactId>springboot-undertow-proxy</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.32</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>21</source>
                    <target>21</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>3.2.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

步驟 2:創(chuàng)建 Undertow 配置類

package com.example.config;

import io.undertow.Handlers;
import io.undertow.server.HttpHandler;
import io.undertow.server.handlers.PathHandler;
import io.undertow.server.handlers.RequestLimitingHandler;
import io.undertow.server.handlers.ResponseCodeHandler;
import io.undertow.server.handlers.proxy.LoadBalancingProxyClient;
import io.undertow.server.handlers.proxy.ProxyHandler;
import io.undertow.util.HeaderMap;
import io.undertow.util.HttpString;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.xnio.OptionMap;

import java.net.URI;

@Configuration
public class UndertowProxyConfig {

    @Bean
    @ConditionalOnProperty(name = "user.enabled", havingValue = "false", matchIfMissing = true)
    public WebServerFactoryCustomizer<UndertowServletWebServerFactory> undertowProxyCustomizer() {
        return factory -> factory.addDeploymentInfoCustomizers(deploymentInfo -> {
            deploymentInfo.addInitialHandlerChainWrapper(handler -> {
                PathHandler pathHandler = Handlers.path(handler);

                // 配置代理路由
                HttpHandler handler1 = createProxyClient("http://127.0.0.1:8081/user");
                HttpHandler handler2 = createProxyClient("http://127.0.0.2:8081/user/users2");

                handler1 = secureProxyHandler(handler1);
                handler1 = createRateLimitingHandler(handler1);

                // 添加路由規(guī)則
                pathHandler.addPrefixPath("/user", handler1);
                pathHandler.addPrefixPath("/user/users2", handler2);

                return pathHandler;
            });
        });
    }
    
    private HttpHandler createProxyClient(String targetUrl) {
        try {
            URI uri = new URI(targetUrl);
            LoadBalancingProxyClient proxyClient = new LoadBalancingProxyClient();
            proxyClient.addHost(uri);
            proxyClient
                    .setConnectionsPerThread(20)
                    .setMaxQueueSize(10)
                    .setSoftMaxConnectionsPerThread(20)
                    .setProblemServerRetry(5)
                    .setTtl(30000);

            return ProxyHandler.builder()
                    .setProxyClient(proxyClient)
                    .setMaxRequestTime(30000)
                    .setRewriteHostHeader(false)
                    .setReuseXForwarded(true)
                    .build();

        } catch (Exception e) {
            throw new RuntimeException("創(chuàng)建代理客戶端失敗", e);
        }
    }

    private HttpHandler secureProxyHandler(HttpHandler proxyHandler) {
        return exchange -> {
            // 移除敏感頭部
            HeaderMap headers = exchange.getRequestHeaders();
            headers.remove("X-Forwarded-Server");

            // 添加安全頭部
            exchange.getResponseHeaders().add(new HttpString("X-XSS-Protection"), "1; mode=block");
            exchange.getResponseHeaders().add(new HttpString("X-Content-Type-Options"), "nosniff");
            exchange.getResponseHeaders().add(new HttpString("X-Frame-Options"), "DENY");

            // 添加代理信息
            headers.add(new HttpString("X-Forwarded-For"), exchange.getSourceAddress().getAddress().getHostAddress());
            headers.add(new HttpString("X-Forwarded-Proto"), exchange.getRequestScheme());
            headers.add(new HttpString("X-Forwarded-Host"), exchange.getHostName());

            proxyHandler.handleRequest(exchange);
        };
    }

    private HttpHandler createRateLimitingHandler(HttpHandler next) {
        // 根據(jù)實際情況調(diào)整
        return new RequestLimitingHandler(1,1,next);
    }

}

高可用配置

要實現(xiàn)真正的高可用反向代理,需要考慮以下幾個關(guān)鍵方面:

1. 負(fù)載均衡策略

Undertow 提供多種負(fù)載均衡策略,可以根據(jù)需求選擇:

@Bean
public LoadBalancingProxyClient loadBalancingProxyClient() {
    LoadBalancingProxyClient loadBalancer = new LoadBalancingProxyClient();
    
    // 配置負(fù)載均衡策略
    loadBalancer.setRouteParsingStrategy(RouteParsingStrategy.RANKED);
    loadBalancer.setConnectionsPerThread(20);

    // 添加后端服務(wù)器
    loadBalancer.addHost(new URI("http://backend1:8080"));
    loadBalancer.addHost(new URI("http://backend2:8080"));
    loadBalancer.addHost(new URI("http://backend3:8080"));
    
    // 設(shè)置會話親和性(可選)
    loadBalancer.addSessionCookieName("JSESSIONID");
    
    return loadBalancer;
}

2. 健康檢查與自動故障轉(zhuǎn)移

實現(xiàn)定期健康檢查,自動剔除不健康節(jié)點:

package com.example.config;

import io.undertow.server.handlers.proxy.LoadBalancingProxyClient;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Component
@ConditionalOnProperty(name = "user.enabled", havingValue = "false", matchIfMissing = true)
@Slf4j
public class BackendHealthMonitor {
    
    private final LoadBalancingProxyClient loadBalancer;
    private final List<URI> backendServers;
    private final RestTemplate restTemplate;
    
    public BackendHealthMonitor(@Value("#{'${user.backends}'.split(',')}") String[] backends,
            LoadBalancingProxyClient loadBalancer) throws URISyntaxException {
        this.loadBalancer = loadBalancer;
        this.restTemplate = new RestTemplate();
        this.backendServers = Arrays.stream(backends)
                .map(url -> {
                    try {
                        return new URI(url);
                    } catch (URISyntaxException e) {
                        throw new RuntimeException(e);
                    }
                })
                .collect(Collectors.toList());
    }
    
    @Scheduled(fixedDelay = 10000) // 每10秒檢查一次
    public void checkBackendHealth() {
        for (URI server : backendServers) {
            try {
                String healthUrl = server.getScheme() + "://" + server.getHost() + ":" + server.getPort() + "/health";
                ResponseEntity<String> response = restTemplate.getForEntity(healthUrl, String.class);
                
                if (response.getStatusCode().is2xxSuccessful()) {
                    loadBalancer.addHost(server);
                    log.info("后端服務(wù) {} 狀態(tài)正常,已添加到負(fù)載均衡", server);
                } else {
                    // 服務(wù)不健康,從負(fù)載均衡器中移除
                    loadBalancer.removeHost(server);
                    log.warn("后端服務(wù) {} 狀態(tài)異常,已從負(fù)載均衡中移除", server);
                }
            } catch (Exception e) {
                // 連接異常,從負(fù)載均衡器中移除
                loadBalancer.removeHost(server);
                log.error("后端服務(wù) {} 連接異常: {}", server, e.getMessage());
            }
        }
    }
}

3. 集群高可用

為確保被代理服務(wù)的高可用,可配置多個代理實例:

user:
  backends: "http://127.0.0.1:8081,http://127.0.0.2:8081"

性能優(yōu)化

要獲得最佳性能,需要調(diào)整 Undertow 的相關(guān)參數(shù)(需要根據(jù)項目實際情況進行測試調(diào)整):

server:
  undertow:
    threads: 
      io: 8                      # IO線程數(shù),建議設(shè)置為CPU核心數(shù)
      worker: 64                 # 工作線程數(shù),IO線程數(shù)的8倍
    buffer-size: 16384           # 緩沖區(qū)大小
    direct-buffers: true         # 使用直接緩沖區(qū)
    max-http-post-size: 10485760 # 最大POST大小
    max-parameters: 2000         # 最大參數(shù)數(shù)量
    max-headers: 200             # 最大請求頭數(shù)量
    max-cookies: 200             # 最大Cookie數(shù)量

連接池優(yōu)化

@Bean
public UndertowServletWebServerFactory undertowFactory() {
    UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
    factory.addBuilderCustomizers(builder -> {
        builder.setSocketOption(Options.KEEP_ALIVE, true)
               .setSocketOption(Options.TCP_NODELAY, true)
               .setSocketOption(Options.REUSE_ADDRESSES, true)
               .setSocketOption(Options.BACKLOG, 10000)
               .setServerOption(UndertowOptions.MAX_ENTITY_SIZE, 16 * 1024 * 1024L)
               .setServerOption(UndertowOptions.IDLE_TIMEOUT, 60 * 1000)
               .setServerOption(UndertowOptions.REQUEST_PARSE_TIMEOUT, 30 * 1000)
               .setServerOption(UndertowOptions.NO_REQUEST_TIMEOUT, 60 * 1000)
               .setServerOption(UndertowOptions.MAX_CONCURRENT_REQUESTS_PER_CONNECTION, 200);
    });
    return factory;
}

安全強化

反向代理需要考慮安全性,可以添加以下配置:

1. 請求頭過濾與重寫

private HttpHandler secureProxyHandler(HttpHandler proxyHandler) {
    return exchange -> {
        // 移除敏感頭部
        HeaderMap headers = exchange.getRequestHeaders();
        headers.remove("X-Forwarded-Server");
        
        // 添加安全頭部
        exchange.getResponseHeaders().add(new HttpString("X-XSS-Protection"), "1; mode=block");
        exchange.getResponseHeaders().add(new HttpString("X-Content-Type-Options"), "nosniff");
        exchange.getResponseHeaders().add(new HttpString("X-Frame-Options"), "DENY");
        
        // 添加代理信息
        headers.add(new HttpString("X-Forwarded-For"), exchange.getSourceAddress().getAddress().getHostAddress());
        headers.add(new HttpString("X-Forwarded-Proto"), exchange.getRequestScheme());
        headers.add(new HttpString("X-Forwarded-Host"), exchange.getHostName());
        
        proxyHandler.handleRequest(exchange);
    };
}

2. 請求限流

private HttpHandler createRateLimitingHandler(HttpHandler next) {
    return new RequestLimitingHandler(100,next);
}

實際案例:某系統(tǒng) API 網(wǎng)關(guān)

以一個電商系統(tǒng)為例,展示 Undertow 反向代理的實際應(yīng)用:

package com.example.config;

import io.undertow.Handlers;
import io.undertow.server.HttpHandler;
import io.undertow.server.handlers.PathHandler;
import io.undertow.server.handlers.proxy.LoadBalancingProxyClient;
import io.undertow.server.handlers.proxy.ProxyHandler;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.URI;

@Configuration
public class EcommerceProxyConfig {

    @Bean
    public WebServerFactoryCustomizer<UndertowServletWebServerFactory> ecommerceProxyCustomizer() {
        return factory -> factory.addDeploymentInfoCustomizers(deploymentInfo -> {
            deploymentInfo.addInitialHandlerChainWrapper(handler -> {
                PathHandler pathHandler = Handlers.path(handler);
                try {
                    // 用戶服務(wù)代理
                    LoadBalancingProxyClient userServiceClient = new LoadBalancingProxyClient();
                    userServiceClient.addHost(new URI("http://user-service-1:8080/api/users"));
                    userServiceClient.addHost(new URI("http://user-service-2:8080/api/users"));

                    // 商品服務(wù)代理
                    LoadBalancingProxyClient productServiceClient = new LoadBalancingProxyClient();
                    productServiceClient.addHost(new URI("http://product-service-1:8080/api/products"));
                    productServiceClient.addHost(new URI("http://product-service-2:8080/api/products"));

                    // 訂單服務(wù)代理
                    LoadBalancingProxyClient orderServiceClient = new LoadBalancingProxyClient();
                    orderServiceClient.addHost(new URI("http://order-service-1:8080/api/orders"));
                    orderServiceClient.addHost(new URI("http://order-service-2:8080/api/orders"));

                    // 路由規(guī)則
                    pathHandler.addPrefixPath("/api/users", createProxyHandler(userServiceClient));
                    pathHandler.addPrefixPath("/api/products", createProxyHandler(productServiceClient));
                    pathHandler.addPrefixPath("/api/orders", createProxyHandler(orderServiceClient));

                    return pathHandler;
                }catch (Exception e){
                    throw new RuntimeException(e);
                }
            });
        });
    }
    
    private HttpHandler createProxyHandler(LoadBalancingProxyClient client) {
        return ProxyHandler.builder()
                .setProxyClient(client)
                .setMaxRequestTime(30000)
                .setRewriteHostHeader(true)
                .build();
    }
}

總結(jié)

Spring Boot 內(nèi)置的 Undertow 反向代理功能為微服務(wù)架構(gòu)提供了一種輕量級的代理解決方案。

雖然功能上可能不如專業(yè)的反向代理服務(wù)器(如 Nginx)那么豐富,但在特定場景下,尤其是希望簡化架構(gòu)、統(tǒng)一技術(shù)棧的情況下,可以作為一種備選方案。

以上就是SpringBoot利用Undertow實現(xiàn)高可用的反向代理配置的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Undertow反向代理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 虛擬機linux中jdk安裝配置方法

    虛擬機linux中jdk安裝配置方法

    這篇文章主要為大家詳細(xì)介紹了虛擬機linux中jdk安裝配置方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • Java——對象初始化順序使用詳解

    Java——對象初始化順序使用詳解

    本篇文章介紹了,Java對象初始化順序的使用。需要的朋友參考下
    2017-04-04
  • 詳解SpringBoot+Dubbo集成ELK實戰(zhàn)

    詳解SpringBoot+Dubbo集成ELK實戰(zhàn)

    這篇文章主要介紹了詳解SpringBoot+Dubbo集成ELK實戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • SpringBoot使用Redis實現(xiàn)消息隊列的方法小結(jié)

    SpringBoot使用Redis實現(xiàn)消息隊列的方法小結(jié)

    在應(yīng)用中把Redis當(dāng)成消息隊列來使用已經(jīng)屢見不鮮了,我想主要原因是當(dāng)代應(yīng)用十有八九都會用到 Redis,因此不用再引入其他消息隊列系統(tǒng),而且Redis提供了好幾種實現(xiàn)消息隊列的方法,用起來也簡單,本文給大家介紹了SpringBoot使用Redis實現(xiàn)消息隊列的方法小結(jié)
    2024-04-04
  • 如何更好的使用Java8中方法引用詳解

    如何更好的使用Java8中方法引用詳解

    在Java8中,我們可以直接通過方法引用來簡寫lambda表達式中已經(jīng)存在的方法,這種特性就叫做方法引用(Method Reference)。下面這篇文章主要給大家介紹了關(guān)于如何更好的使用Java8中方法引用的相關(guān)資料,需要的朋友可以參考下。
    2017-09-09
  • 刪除JAVA集合中元素的實現(xiàn)代碼

    刪除JAVA集合中元素的實現(xiàn)代碼

    有時候我們要刪除集合中的某些元素,那么就可以參考下面的代碼
    2013-07-07
  • Spring Cloud Config配置文件使用對稱加密的方法

    Spring Cloud Config配置文件使用對稱加密的方法

    Spring Cloud Config提供了兩種加密解密方式,一種是對稱加密,一種是非對稱加密。這篇文章將先展示如何使用對稱加密。感興趣的朋友跟隨腳步之家小編一起學(xué)習(xí)吧
    2018-05-05
  • SpringBoot-Mail工具實現(xiàn)郵箱驗證碼登錄注冊功能

    SpringBoot-Mail工具實現(xiàn)郵箱驗證碼登錄注冊功能

    現(xiàn)在許多pc程序都有著使用郵箱驗證碼實現(xiàn)登錄注冊的功能,那么我們應(yīng)該如何完成郵箱驗證碼功能呢,我們可以使用springboot內(nèi)置的springboot-mail再結(jié)合redis來完成這個功能,感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • Java實現(xiàn)curl調(diào)用帶參數(shù)接口方法

    Java實現(xiàn)curl調(diào)用帶參數(shù)接口方法

    本文主要介紹了Java實現(xiàn)curl調(diào)用帶參數(shù)接口方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • java拼接字符串時去掉最后一個多余逗號的方法

    java拼接字符串時去掉最后一個多余逗號的方法

    這篇文章主要介紹了java拼接字符串時去掉最后一個多余逗號的方法,實例分析了java操作字符串的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-03-03

最新評論

黔南| 长寿区| 团风县| 饶阳县| 普兰县| 来宾市| 颍上县| 彭水| 章丘市| 左云县| 建平县| 崇仁县| 康保县| 额尔古纳市| 汨罗市| 庆城县| 财经| 松江区| 玉山县| 克东县| 黄冈市| 阳山县| 衡山县| 衡阳县| 合江县| 衡阳市| 开化县| 铅山县| 黑山县| 台北市| 遵义县| 靖西县| 兴安盟| 马关县| 雅安市| 平果县| 阿城市| 绥滨县| 天全县| 江都市| 科技|