Nginx+springcloud gateWay 实现高可用网关集群

Nginx+springcloud gateWay 实现高可用网关集群
游龙当归海,海不迎我自来也!

以 下 为 正 文

首先明确一点。本文实现功能如下图:

自己画的2333

nginx概述

nginx是一个开源的,支持高性能、高并发的www服务和代理服务软件。

它是一个俄罗斯人lgor sysoev开发的,作者将源代码开源出来供全球使用。 nginx比它大哥apache性能改进许多,nginx占用的系统资源更少,支持更高的并发连接,有更高的访问效率。

nginx不但是一个优秀的web服务软件,支持反向代理负载均衡,以及缓存服务(动静分离)。 安装简单,方便,灵活。

高并发能支持几万并发连接,资源消耗少,在3万并发连接下开启10个nginx线程消耗的内存不到200M 。

springcloud gateWay概述

springCloud Gateway 是SpringCloud的一个全新项目,基于Spring 5.0 + SpringBoot 2.0 。旨在提供一种简单而有效的方式对API进行路由,以及强大的过滤功能:熔断、限流、监控、校验、鉴权等。

Gateway作为SpringCloud生态系统中的网关,目的是替换已经进入维护停更阶段的Zuul。并没有对Zuul 2.0 进行集成(zuul 太不争气),为了提高性能,Gateway基于WebFlux框架实现,而WebFlux框架底层则使用高性能的通信框架Netty。

Gateway网关具有如下特性:

  1. 动态路由,能匹配任何请求属性。
  2. 可以对指定路由进行predicate(断言)和Filter(过滤)。
  3. 集成了Hystrix的熔断功能。
  4. 请求限流
  5. 路径重写

其中三个核心概念:

Route(路由)

构建网关的基本模块,由ID,目标URI,一系列的断言和过滤器组成,如果断言为True则匹配该路由。

Predicate(断言)

参考java8的java.util.function.Predicate。开发人员可以匹配HTTP请求中的所有内容(例如请求头或者请求参数)如果请求与断言相匹配则进行相应的路由转发

Filter(过滤)

指Spring框架中GateWayFilter的实例,使用过滤器,可以在请求被路由前后对此请求进行判断或修改。

附上官网的流程图:

安装nginx

过程非常简单:

建立nginx的yum仓库 :

sudo rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

安装:

yum install -y nginx

启动nginx服务、查看状态、 重新加载config配置

systemctl start nginx.service
systemctl status nginx.service
systemctl reload nginx.service  # 每次修改配置文件后,只需要执行此命令即可
nginx默认的网站目录为: /usr/share/nginx/html
nginx全局的配置文件为:/etc/nginx/nginx.conf
nginx默认的配置文件为: /etc/nginx/conf.d/default.conf
nginx日志文件目录为:/var/log/nginx/

新建Gateway服务

主要依赖:

<!-- gateway -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- redis的reactive依赖用于限流分布式 -->
<!--<dependency>-->
    <!--<groupId>org.springframework.boot</groupId>-->
    <!--<artifactId>spring-boot-starter-data-redis-reactive</artifactId>-->
<!--</dependency>-->
<!-- hystrix -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- eureka-client 网关作为微服务也要注册进去 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

配置:

server:
  port: 9527

spring:
  application:
    name: cloud-gateway

  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedHeaders: "*"
            allowedOrigins: "*"
#            allowedOrigins: "http://localhost/"  # 允许从所有allowedMethods配置的源请求发出CORS请求。
            allowedMethods:
              - POST
              - OPTIONS
              - GET
      httpclient:
        connect-timeout: 5000  # 毫秒。
        response-timeout: 5s
      discovery:
        locator:
          enabled: true        
      routes:
        - id: a                # 路由的id,格式无固定规则但要求唯一,建议配合服务名                 
          uri: lb://CLOUD-HYSTRIX-PAYMENT-SERVER   #lb://服务名, 由网关实现负载均衡,底层使用ribbon
          predicates:
            - Path=/pay/**               # 断言,路径匹配则进行路由
          metadata:                      # 单独配置此路由的超时时间,要比所有已存在服务所配置的超时时间长或者相等,否则504
            response-timeout: 10000
            connect-timeout: 10000
          filters:
            - name: Hystrix              
              args:
                name: fallback
                fallbackUri: forward:/fallback # fallback对应的uri,这里的uri仅支持forward
#            - StripPrefix=1 # 去掉前缀,具体实现参考StripPrefixGatewayFilterFactory

        - id: b
          uri: lb://CLOUD-HYSTRIX-PAYMENT-SERVER   
          predicates:
            - Path=/lb
        - id: c
          uri: lb://CLOUD-HYSTRIX-PAYMENT-SERVER  
          predicates:
            - Path=/payment/**
           - Header=Authorization,(token&amp;)(.*?)      

eureka:
  instance:
    instance-id: cloud-gateway-9527     
    prefer-ip-address: true      
  client:
    fetch-registry: true        
    register-with-eureka: true  
    service-url:
      defaultZone: http://192.168.31.105:17111/eureka/,http://192.168.31.106:17111/eureka/,http://192.168.31.107:17111/eureka/

info:
  myInfo: 网关9527
  app.name: cloud2020
  company.name: lzyz.fun

大体思路是:建立两个Gateway服务(9527,9528)注册进中心。当请求经过nginx则会被负载均衡将请求分发给两个gaetway服务,再由gateway服务转发给对应的业务处理服务(8001,8002)进行处理和返回结果。

配置nginx负载均衡:

首先修改 nginx.conf 文件,添加服务器网关端口集群 :

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

# 配置Nginx worker进程最大打开文件数
worker_rlimit_nofile 65535;

events {
    # 单个进程允许的客户端最大连接数
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    # 日志格式
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    #tcp_nopush     on;
    keepalive_timeout  65;
    #gzip  on;
    
    
    # 配置服务器网关端口集群
    upstream  gatewayServer{
        server 192.168.31.124:9527 weight=1;
        server 192.168.31.124:9528 weight=1;
    }


    # 导入其他配置
    include /etc/nginx/conf.d/*.conf;
    
    
    # 隐藏版本号
    server_tokens on;   
}

然后在 /etc/nginx/conf.d 下建立一个fuzh1.conf 文件,添加配置:

server {
    listen       28080;                  # 服务监听端口
    server_name  192.168.31.124;         # 服务的域名或IP

    #charset koi8-r;
    access_log  /var/log/nginx/host.access.log  main;   

    location / {
        proxy_pass http://gatewayServer/;  # 转发地址
    }   
}

刷新配置:

systemctl reload nginx.service

解释下。 nginx会监听28080端口的请求,一旦有请求,将分发给两个gateway服务。

测试

接下来启动服务,可以在注册中心发现两个服务,一个业务处理服务集群,一个网关集群:

访问105机器的nginx首页是否正常

接下来访问28080端口,由于在gateway网关做了鉴权限制,没有token会返回错误信息:

看起来正常。接下来使用带token的请求来测试负载均衡是否正常:

可以观察到返回的serverPort分别是8001和8002,即实现了通过nginx实现对gateway的负载均衡和高可用。 即使gatway挂掉一台9527,还是会有另一台9528撑着。 如果不放心还可以对Nginx做一主一备处理。

Comments

No comments yet. Why don’t you start the discussion?

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注