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/n/371067.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
NKOANNKOAN
上一篇 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

发表回复

登录后才能评论