zoukankan      html  css  js  c++  java
  • Spring Cloud (七):API 网关

    在微服务架构中,不同服务有不同的地址,客户端需要和多个服务交互,这会带来一些问题

    • 客户端需要多次请求不同的微服务,增加复杂性
    • 存在跨域请求
    • 每个微服务都有独立认证
    • 微服务重构时,客户端也要跟着改

    API 网关就是客户端和服务端的中间层,所有请求都会先经过 API 网关,再由 API 网关发给后端的微服务

    使用了 API 网关后可以做统一的登录、认证、监控、日志、限流、负载均衡、转发,简化了前后端的交互和开发

    API 网关有 nginx,kong,zuul,Spring Cloud Gateway,F5 等




    zuul

    zuul 是 Netflix 开源的微服务网关组件,它可以和 Eureka、Robbin、Hystrix 等组件配合使用

    zuul 的功能

    • 认证和安全
    • 预警和监控
    • 动态路由
    • 压力测试
    • 负载均衡
    • 静态处理
    • 多区域弹性

    启动 zuul 的代码如下

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            </dependency>
    
    @SpringBootApplication
    @EnableZuulProxy
    public class ZuulServerApplication {
        public static void main(String[] args) {
            SpringApplication.run(ZuulServerApplication.class, args);
        }
    }
    
    server:
      port: 9000
    
    zuul:
      prefix: /api   # 访问网关路径的前缀
      routes:
        service-01:                       # 服务的名字,可以是任意名字,不会出现在 zuul 的 url 中
          path: /product-service/**       # 将服务的这个 path,映射到下面的 URL,或是 service id (如果使用了 Consul 或 Eureka)
          url: http://localhost:8501      # 比如 zuul-host:zuul-port/api/product-service/product/1 会被映射成 http://localhost:8501/product/1
          # service-id: consul-service-1
        service-02:
          path: /hello-service/**
          url: http://localhost:8505
          # service-id: consul-service-1
      retryable: true
    

    访问 http://localhost:9000/api/product-service/product/1
    实际上会被转发到 http://localhost:8501/product/1


    Spring Cloud Gateway

    zuul 有版本 1 和版本 2,spring cloud 集成的是版本 1,后续可能不会再改,而是推出 Spring Cloud Gateway

    Spring Cloud Gateway 是基于 WebFlux 框架实现的,而 WebFlux 框架底层则使用了高性能的 Reactor 模式通信框架 Netty

    Spring Cloud Gateway 的特性 (https://github.com/spring-cloud/spring-cloud-gateway)

    • 基于Spring 5, Spring Boot 2 and Project Reactor
    • 动态路由
    • 基于 HTTP 请求的任意属性(Path, Method, Header, Host, etc…)做路由匹配
    • Filters 作用于匹配路由
    • Filters 可以修改 HTTP 请求和响应
    • 支持 Spring Cloud DiscoveryClient
    • 支持负载均衡、限流熔断等功能

    spring cloud gateway 的匹配机制比较强大,启动 spring cloud gateway 的代码如下

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
    

    注意需要移除 spring-boot-starter-web,并且如果有一些 dependency 间接依赖 spring-boot-starter-web,那么需要通过 exclude 排除掉,不然会报错:Consider defining a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' in your configuration.

    如果用到了 hystrix 的容错功能,那么还要把 hystrix 的依赖添加上

    @SpringBootApplication
    public class SpringCloudGatewayApplication {
        public static void main(String[] args) {
            SpringApplication.run(SpringCloudGatewayApplication.class, args);
        }
    }
    
    server:
      port: 9000
    
    spring:
      cloud:
        gateway:
          routes:
          - id: service-01               ## 每个路由的 id,任意名字,不会出现在 url 中
            uri: http://localhost:8501   ## 和这个路由匹配的请求都转发到 http://localhost:8501
            order: 0                     ## 优先级,一个请求有可能和多个路由匹配,会执行高优先级的路由
              
            predicates:                  ## 谓词,满足下面列举的条件的请求,就和这个路由匹配上
            - Path=/product-service/**   ## 匹配 url 为 /product-service/** 的请求
                                         ## 即 gateway-host:gateway-port/product-service/** 会被转发到 http://localhost:8501/**
              
            filters:                     ## 过滤,对请求做一些处理(下面这里是两个过滤器)
            - StripPrefix=1              ## 第一个过滤器:截断路径中的第一个字段,比如 /test/abc 变成 /abc
            - name: Hystrix              ## 第二个过滤器:通过 Hystrix 做熔断
              args:
                name: fallbackCmdA  
                fallbackUri: forward:/fallbackA    ## 将 forward 服务的 fallbackA 路径的输出作为熔断的返回
    
    hystrix:
      command:
        fallbackCmdA:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 5000
    

    也可以通过代码实现这些配置功能

    spring cloud gateway 的配置功能很强,下面再举一些例子

    # 请求中包含 id 参数的即可匹配路由,比如
    # localhost:9000?id=2
    predicates:
    - Query=id
    
    # 请求中包含 id 参数,且 id 参数以 abc 开头的即可匹配路由,比如
    # localhost:9000?id=abc123
    # 注意这里的 abc. 是正则表达式
    predicates:
    - Query=id, abc.
    
    # 请求的 header 中包含 X-Request-Id 参数,且参数的值是数字,即可匹配路由,比如
    # curl -H "X-Request-Id:88" localhost:9000
    predicates:
    - Header=X-Request-Id, d+
    
    # 请求的 cookie 中包含 sessionId,且值为 test,即可匹配路由,比如
    # curl --cookie "sessionId=test" localhost:9000
    predicates:
    - Cookie=sessionId, test
    
    # GET 请求即可匹配路由
    predicates:
    - Method=GET
    
    # 请求的路径满足要求,即可匹配路由,比如
    # curl localhost:9000/foo/1
    # curl localhost:9000/foo/test
    predicates:
    - Path=/foo/{segment}
    
    # 请求的远程地址满足要求即可匹配路由
    predicates:
    - RemoteAddr=192.168.1.1/24
    
    # 可以组合使用
    predicates:
    - Path=/product-service
    - Method=GET
    - Query=id
    

    Spring Cloud Gateway 的功能配置比 zuul 要多


    nginx

    nginx 的作用

    • 负载均衡
    • 地址映射和端口映射
    • 静态文件支持、伪静态
    • 缓存静态和伪静态页面
    • 缓冲请求和响应
    • 高可用性,高并发抗压能力,都比较强
    • 访问控制、限速等功能

    安装 Nginx

    sudo apt-get install nginx
    

    Nginx 配置

    /etc/nginx/nginx.conf
    

    这个配置文件会引入下面两个目录的配置文件

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
    

    创建 /etc/nginx/conf.d/test.conf (配置文件可以有多个)

    server {
        listen       80;
        server_name  localhost;
    
        # location 的 URL 匹配语法
        # ~* 表示正则表达式,不区分大小写
        # ~  表示正则表达式,要区分大小写
        # =  表示精确匹配
        # 没有修饰符的,以指定模式开始,比如 location / 匹配所有以 / 开始的 URL
    
        # 静态页面,直接读取 html 文件
        location ~* .*.html$ {
            gzip on;
            root /usr/share/nginx/html;
        }
            
        # 动态页面,转发给后端
        location / {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    

    Nginx 性能强,稳定性高,适合作为全局的网关,但有的功能不具备,比如熔断等


    kong

    kong 是一个基于 nginx 的,用 nginx_lua 模块编写扩展插件的网关
    kong 可以使用 Cassandra/PostgreSQL 数据库来存储数据

    https://docs.konghq.com/install/ubuntu/

     $ sudo apt-get update
     $ sudo apt-get install -y apt-transport-https curl lsb-core
     $ echo "deb https://kong.bintray.com/kong-deb `lsb_release -sc` main" | sudo tee -a /etc/apt/sources.list
     $ curl -o bintray.key https://bintray.com/user/downloadSubjectPublicKey?username=bintray
     $ sudo apt-key add bintray.key
     $ sudo apt-get update
     $ sudo apt-get install -y kong
    

    配置文件

    cp /etc/kong/kong.conf.default /etc/kong/kong.conf
    

    如果配置数据库

    CREATE USER kong;
    CREATE DATABASE kong OWNER kong;
    
    kong migrations bootstrap [-c /etc/kong/kong.conf]
    

    如果不配置数据库

    ## 会在当前路径生成 kong.yml
    kong config init
    
    ## 在 kong.conf 文件里把数据库选项关掉
    database = off
    declarative_config = /path/to/kong.yml
    

    启动 kong

    kong start [-c /etc/kong/kong.conf] [--nginx-conf /path/to/custom_nginx.template]
    

    kong 默认监听以下端口

    • 8000:监听客户端的 HTTP 请求,转发到后端服务
    • 8443:监听客户端的 HTTPS 请求,转发到后端服务,可以 disable
    • 8001:监听 Admin API HTTP 请求,用于配置 Kong
    • 8444:监听 Admin API HTTPS 请求,用于配置 Kong

    可以通过向 8001 端口发送 POST 请求进行配置

    重载 kong

    kong reload
    

    停止 kong

    kong stop
    

    kong 可以通过 --nginx-conf 指定 nginx 配置


    F5

    F5 是直接通过硬件实现,和系统及应用无关,只从网络层判断处理,性能强,缺点是成本高,配置可能比其他的复杂



  • 相关阅读:
    Linux 下升级python和安装pip
    All of Me
    MangataのACM模板
    HDU1517 A Multiplication Game (博弈论+思维)
    Home_W的握手问题(思维+打表)
    Home_W的几何题 (计算几何)
    stone (组合数学 + Lucas定理)
    随笔分类
    HDU 5586 Sum (预处理 + 动态规划)
    POJ2104 K-th Number (平方分割 + 二分)
  • 原文地址:https://www.cnblogs.com/moonlight-lin/p/14226264.html
Copyright © 2011-2022 走看看