zuul與nginx的區別

一、概述

zuul和nginx都是一種代理服務器,它們主要的目的都是將客戶端請求轉發到後端的服務器上。但是,它們之間還是有一些區別的。

二、負載均衡

nginx早期就引入了負載均衡的概念,它可以通過一些算法將請求分發到多台服務器上,從而降低單機的壓力,提高反應速度。而zuul的負載均衡是在Netflix的Eureka上實現的,基於Ribbon和RestTemplate實現,在請求到達zuul後,zuul會向Eureka註冊中心查詢可用的服務,並選出一台最優的服務器,將請求轉發到這台服務器上。

此外,在使用zuul實現負載均衡時,我們還需要在服務提供者中配置對應的註解。

    
        @RestController
        @RequestMapping("/api")
        public class ApiController {
            
            @Autowired
            private RestTemplate restTemplate;
            
            @ApiOperation("測試zuul的負載均衡")
            @GetMapping("/test")
            public String test() {
                return "This is from provider " + restTemplate.getForEntity("http://provider/test", String.class).getBody();
            }
        }
    

在上述代碼中,我們可以看到,@Autowired註解引入了RestTemplate,這是實現負載均衡的核心組件,而restTemplate.getForEntity()方法中的URL參數中只寫了服務的名稱,比如”provider”,而沒有寫具體的IP地址和端口號,這是因為要使用zuul的負載均衡功能。

三、動態路由

zuul相對於nginx的另一個優勢在於它支持動態路由。在微服務中,如果有新的服務需要加入,或者某個服務需要下線,這個時候我們就需要修改nginx的配置文件並重啟nginx,而這個過程可能比較繁瑣。但是,在zuul中,我們只需要在Eureka上註冊或者下線服務,zuul可以動態地檢測這個變化,並相應地調整路由規則,從而實現自動化的服務發現和動態路由。

以下是一個實現了動態路由功能的zuul網關。

    
        @SpringBootApplication
        @EnableZuulProxy
        public class GatewayApplication {
        
            public static void main(String[] args) {
                SpringApplication.run(GatewayApplication.class, args);
            }
        
            @Value("${spring.cloud.config.uri}")
            private String url;
        
            @Autowired
            private DiscoveryClient discoveryClient;
        
            @EventListener
            public void onApplicationEvent(ApplicationReadyEvent event) {
                refreshRoute();
            }
        
            @Scheduled(fixedRate = 60000)
            public void refreshRoute() {
                List instances = discoveryClient.getInstances("zuul");
                if (!instances.isEmpty()) {
                    ServiceInstance serviceInstance = instances.get(0);
                    String path = "/actuator/bus-refresh";
                    String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + path;
                    RestTemplate restTemplate = new RestTemplate();
                    restTemplate.postForEntity(url, null, null);
                }
            }
        }
    

上述代碼實現了通過定時器定時向Eureka Server查詢可用服務並更新路由規則。我們可以注意到,使用@EnableZuulProxy註解開啟了zuul的代理功能,@Autowired引入了DiscoveryClient,它能查詢Eureka上註冊的服務。在事件監聽方法onApplicationEvent()中,我們在應用啟動時即刻啟動一次路由刷新,以防重啟zuul前Eureka上已有服務改變。在定時任務方法refreshRoute()中,我們通過RestTemplate發送POST請求以觸發路由刷新。

四、動態訪問日誌

nginx在訪問日誌這個方面表現異常優秀,可以實時記錄請求日誌,並支持不同格式的日誌輸出。但是,在zuul這個框架中,要實現動態日誌需要藉助第三方工具。最常見的做法是結合Logstash和Elasticsearch,這樣我們就可以把所有的請求日誌都存儲到Elasticsearch上,並通過Kibana進行可視化展示和分析。

以下是一個實現動態日誌功能的zuul網關。

    
        #zuul配置文件
        zuul:
          routes:
            user:
              path: /user/**
              url: http://localhost:8080
            product:
              path: /product/**
              url: http://localhost:8081
          request:
            occlude-headers:
        
        #Logback日誌配置文件
        
        
            
                
                
                    %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
                
            
            
                
                ./logs/api-apm.log
                true
                
                    %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
                    UTF-8
                
                
                    ./logs/%d{yyyy-MM-dd}/api-apm-%d{yyyy-MM-dd_HH}.log
                    7
                
            
            
                
                
            
        
        
        #Spring Boot啟動類
        @SpringBootApplication(scanBasePackages = "com.example")
        @EnableZuulProxy
        public class GatewayApplication {
        
            public static void main(String[] args) {
                SpringApplication.run(GatewayApplication.class, args);
            }
        
            @Bean
            public ConfigurableServletWebServerFactory configurableServletWebServerFactory() {
                TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
                factory.addConnectorCustomizers((connector -> {
                    AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) connector.getProtocolHandler();
                    protocol.setCompression("on");
                    protocol.setCompressionMinSize(1024);
                    String[] mimeTypes = protocol.getCompressableMimeTypes();
                    List mimeList = new ArrayList(Arrays.asList(mimeTypes));
                    mimeList.add("application/json");
                    protocol.setCompressableMimeTypes(mimeList.toArray(new String[0]));
                }));
                return factory;
            }
        
            @Bean
            public PatternLayoutEncoder encoder() {
                PatternLayoutEncoder encoder = new PatternLayoutEncoder();
                encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n");
                encoder.setCharset(Charset.forName("UTF-8"));
                return encoder;
            }
        
            @Bean
            public LoggerFilter loggerFilter() {
                LoggerFilter loggerFilter = new LoggerFilter();
                loggerFilter.setAppenders("api-apm");
                loggerFilter.setAdditive(false);
                return loggerFilter;
            }
        
            @Bean
            public Logger logger() {
                Logger logger = (Logger) LoggerFactory.getLogger("com.netflix.zuul.monitoring.MonitoringHelper");
                logger.setLevel(Level.ERROR);
                return logger;
            }
        }
    

在上述代碼中,我們使用Logback配置了日誌相關信息,通過@EnableZuulProxy註解啟用了zuul的服務代理功能。在@Bean註解的方法中,我們還配置了Tomcat的壓縮策略和編碼信息,以及zuul的日誌過濾器和日誌級別。

總之,zuul和nginx二者的優劣勢都很明顯,它們的選擇要根據實際使用場景來判斷。在微服務架構中,通常會使用zuul作為服務網關,以實現動態路由、負載均衡等功能。但是,在靜態網頁服務器、WEB路由、反向代理等方面,nginx的性能和穩定性都是值得稱讚的。

原創文章,作者:NKOAN,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/371067.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
NKOAN的頭像NKOAN
上一篇 2025-04-23 00:48
下一篇 2025-04-23 00:48

相關推薦

  • Python中new和init的區別

    new和init都是Python中常用的魔法方法,它們分別負責對象的創建和初始化,本文將從多個角度詳細闡述它們的區別。 一、創建對象 new方法是用來創建一個對象的,它是一個類級別…

    編程 2025-04-29
  • Sublime Test與Python的區別

    Sublime Text是一款流行的文本編輯器,而Python是一種廣泛使用的編程語言。雖然Sublime Text可以用於編寫Python代碼,但它們之間有很多不同之處。接下來從…

    編程 2025-04-29
  • Shell腳本與Python腳本的區別

    本文將從多個方面對Shell腳本與Python腳本的區別做詳細的闡述。 一、語法差異 Shell腳本和Python腳本的語法存在明顯差異。 Shell腳本是一種基於字符命令行的語言…

    編程 2025-04-29
  • Python中while語句和for語句的區別

    while語句和for語句是Python中兩種常見的循環語句,它們都可以用於重複執行一段代碼。然而,它們的語法和適用場景有所不同。本文將從多個方面詳細闡述Python中while語…

    編程 2025-04-29
  • Web程序和桌面程序的區別

    Web程序和桌面程序都是進行軟件開發的方式,但是它們之間存在很大的區別。本文將從多角度進行闡述。 一、運行方式 Web程序運行於互聯網上,用戶可以通過使用瀏覽器來訪問它。而桌面程序…

    編程 2025-04-29
  • TensorFlow和Python的區別

    TensorFlow和Python是現如今最受歡迎的機器學習平台和編程語言。雖然兩者都處於機器學習領域的主流陣營,但它們有很多區別。本文將從多個方面對TensorFlow和Pyth…

    編程 2025-04-28
  • 麥語言與Python的區別

    麥語言和Python都是非常受歡迎的編程語言。它們各自有自己的優缺點和適合的應用場景。本文將從語言特性、語法、生態系統等多個方面,對麥語言和Python進行詳細比較和闡述。 一、語…

    編程 2025-04-28
  • MySQL bigint與long的區別

    本文將從數據類型定義、存儲空間、數據範圍、計算效率、應用場景五個方面詳細闡述MySQL bigint與long的區別。 一、數據類型定義 bigint在MySQL中是一種有符號的整…

    編程 2025-04-28
  • Python與C語言的區別和聯繫

    Python與C語言是兩種常用的編程語言,雖然兩者都可以用於編寫軟件程序,但是它們之間有很多不同之處。本文將從多個方面對Python與C語言的區別和聯繫進行詳細的闡述。 一、語法特…

    編程 2025-04-28
  • Python中深拷貝和淺拷貝的區別

    本文將從以下幾個方面對Python中深拷貝和淺拷貝的區別做詳細的闡述,包括:拷貝的含義、變量和對象的區別、淺拷貝的示例、深拷貝的示例、可變對象和不可變對象的區別、嵌套的數據結構以及…

    編程 2025-04-28

發表回復

登錄後才能評論