• Envoy实现.NET架构的网关(一)静态配置与文件动态配置


    什么是Gateway

    在微服务体系结构中,如果每个微服务通常都会公开一组精细终结点,这种情况可能会有以下问题

    1. 如果没有 API 网关模式,客户端应用将与内部微服务相耦合
    2. 在客户端应用中,单个页面/屏幕可能需要多次调用多个服务。 
    3. 如果没有网关,所有微服务必定会暴露在“外部世界”中。
    4. 每个公开发布的微服务都必须处理授权和 SSL 等问题。

    而Gateway可以为微服务组提供单一入口点,API 网关位于客户端应用和微服务之间。 它充当反向代理,将请求从客户端路由到服务。 它还可以提供其他跨领域功能,例如身份验证、SSL 终止和缓存

    什么是Envoy

    Envoy 是专为大型现代 SOA(面向服务架构)架构设计的 L7 代理和通信总线,它有以下优势

    1. C++11编写,原生代码高性能
    2. L3/L4 filter架构,例如TCP代理
    3. HTTP L7 filter架构,缓存,限速,路由/转发
    4. 顶级HTTP2与GRPC支持
    5. 服务发现与动态配置
    6. 健康检查
    7. 高级负载均衡

    我们可以借助Envoy实现API Gateway。Envoy通过yaml配置文件来组织网关的信息。下面来说说Envoy中的核心概念

    .NET网关与Gateway实战-Envoy与kong课程希望大家支持  https://ke.qq.com/course/4033027?tuin=1271860f

    Listener

    一个命名的网络地址,可以被下游客户端连接,它的配置样式如下:

    static_resources:
      listeners:
      - name: listener_0
        address:
          socket_address:
            protocol: TCP
            address: 0.0.0.0
            port_value: 10000

    此配置说明Envoy监听在10000端口,下游客户端可以通过此端口与Envoy交互

    L3/L4过滤器Filter

    L3/L4过滤器Filter可以帮我们实现如:HTTP连接管理,限速,TCP代理等功能,它的配置样式如下:

        filter_chains:
        - filters:
          - name: envoy.filters.network.http_connection_manager
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
              scheme_header_transformation:
                scheme_to_overwrite: http
              stat_prefix: ingress_http
              route_config:
                name: local_route
                virtual_hosts:
                - name: local_service
                  domains: ["*"]
                  routes:
                  - match:
                      prefix: "/"
                    route:
                      host_rewrite_literal: 192.168.43.94
                      cluster: service_envoyproxy_io
              http_filters:
              - name: envoy.filters.http.router

    此配置说明通过HttpConnectionManager这个过滤器来接受HTTP请求,并将请求通过router过滤器的配置转发到service_envoyproxy_io这个上游集群

    Upstream Cluster

    Envoy 的集群管理器管理所有配置的上游集群,用来真正处理Envoy接受的请求,其配置样式如下:

    clusters:
      - name: service_envoyproxy_io
        connect_timeout: 30s
        type: strict_dns
        dns_lookup_family: V4_ONLY
        lb_policy: ROUND_ROBIN
        load_assignment:
          cluster_name: service_envoyproxy_io
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: 192.168.43.94
                    port_value: 5000

    此配置说明Envoy会将请求转发到192.168.43.94:5000这个地址。

    调用逻辑我们总结如下,Listener接受请求,将请求交给过滤器,过滤器处理完后,根据路由规则将请求转发给上游集群,上游集群中的endpoint会真正处理请求。

    运行Envoy

    我们通过docker运行一个默认Envoy容器

    docker run --rm -it -p 9901:9901 -p 10000:10000 envoyproxy/envoy-dev

    访问http://localhost:10000/,发现其跳转到Envoy官网

     

     我们进入容器查看其配置,发现其最终会将请求转发到www.envoyproxy.io

    cat /etc/envoy/envoy.yaml
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: www.envoyproxy.io
                    port_value: 443

    静态文件配置

    我们现在通过Envoy来实现我们自己的网关。静态文件配置是我们把配置信息提前配置好,Envoy启动后不可修改配置内容

    准备服务

    我们准备两个.NET WebAPI,server1与server2,其中分别创建NameController,并新建Get方法

    Server1

          [HttpGet]
            public string Get()
            {
                _logger.LogInformation("call server1");
                var req = Request;
                return "server1";
            }

    Server2

            [HttpGet]
            public string Get()
            {
                _logger.LogInformation("call server2");
                var req = Request;
                return "server2";
            }

    并将server1的启动端口指定为5000,将server2的启动端口指定为5001

    Server1

    webBuilder.UseUrls("http://*:5555").UseStartup<Startup>();

    Server2

    webBuilder.UseUrls("http://*:5001/").UseStartup<Startup>();

    我们启动Server1与Server2

    准备Envoy配置

    我们将上节课的默认Envoy配置文件从容器中取出,并作修改如下

    admin:
      address:
        socket_address:
          protocol: TCP
          address: 0.0.0.0
          port_value: 9901
    static_resources:
      listeners:
      - name: listener_0
        address:
          socket_address:
            protocol: TCP
            address: 0.0.0.0
            port_value: 10000
        filter_chains:
        - filters:
          - name: envoy.filters.network.http_connection_manager
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
              scheme_header_transformation:
                scheme_to_overwrite: http
              stat_prefix: ingress_http
              route_config:
                name: local_route
                virtual_hosts:
                - name: local_service
                  domains: ["*"]
                  routes:
                  - match:
                      prefix: "/"
                    route:
                      host_rewrite_literal: 192.168.43.94
                      cluster: service_envoyproxy_io
              http_filters:
              - name: envoy.filters.http.router
      clusters:
      - name: service_envoyproxy_io
        connect_timeout: 30s
        type: static
        # Comment out the following line to test on v6 networks
        dns_lookup_family: V4_ONLY
        lb_policy: ROUND_ROBIN
        load_assignment:
          cluster_name: service_envoyproxy_io
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: 192.168.43.94
                    port_value: 5000
            - endpoint:
                address:
                  socket_address:
                    address: 192.168.43.94
                    port_value: 5001

    我们启动Envoy,验证配置是否正确

    docker run --rm -it -p 9901:9901 -p 10000:10000 -v D:/gateway/envoy/config/static/envoy.yaml:/etc/envoy/envoy.yaml -v D:/gateway/envoy/logs:/logs envoyproxy/envoy-dev  -c /etc/envoy/envoy.yaml --log-path logs/custom.log

    调用api,发现其实现了负载

    http://localhost:10000/Name

    动态文件配置

    动态文件可以帮助我们实现当文件发生更改时,Envoy 将自动更新其配置。

    修改静态文件,将其中的cluster提取到cds.yaml文件中

    resources:
    - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
      name: example_proxy_cluster
      type: STRICT_DNS
      typed_extension_protocol_options:
        envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
          "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
          explicit_http_config:
            http_protocol_options: {}
      load_assignment:
        cluster_name: example_proxy_cluster
        endpoints:
        - lb_endpoints:
          - endpoint:
              address:
                socket_address:
                  address: 192.168.43.94
                  port_value: 5000

    将listener提取到lds.yaml文件中

    resources:
    - "@type": type.googleapis.com/envoy.config.listener.v3.Listener
      name: listener_0
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 10000
      filter_chains:
      - filters:
        - name: envoy.http_connection_manager
          typed_config:
            "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
            stat_prefix: ingress_http
            http_filters:
            - name: envoy.filters.http.router
            route_config:
              name: local_route
              virtual_hosts:
              - name: local_service
                domains:
                - "*"
                routes:
                - match:
                    prefix: "/envoyapi/"
                  route:
                    prefix_rewrite: "/"
                    host_rewrite_literal: 192.168.43.94
                    cluster: example_proxy_cluster

    修改envoy.yaml让其引用lds.yaml与cds.yaml文件

    admin:
      address:
        socket_address:
          protocol: TCP
          address: 0.0.0.0
          port_value: 9902
    node:
      cluster: test-cluster
      id: test-id
    dynamic_resources:
      cds_config:
        path: /etc/envoy/cds.yaml
      lds_config:
        path: /etc/envoy/lds.yaml

    启动Envoy

    docker run --rm -it -p 9902:9902 -p 10000:10000 -v D:/gateway/envoy/config/dynamic/:/etc/envoy/ -v D:/gateway/envoy/logs:/logs envoyproxy/envoy-dev  -c /etc/envoy/envoy.yaml --log-path logs/custom.log

    调用api,发现调用成功

    http://localhost:10000/envoyapi/Name

    修改动态文件配置

    修改cds.yaml,将endpoint端口设置为5001

    resources:
    - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
      name: example_proxy_cluster
      type: STRICT_DNS
      typed_extension_protocol_options:
        envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
          "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
          explicit_http_config:
            http_protocol_options: {}
      load_assignment:
        cluster_name: example_proxy_cluster
        endpoints:
        - lb_endpoints:
          - endpoint:
              address:
                socket_address:
                  address: 192.168.43.94
                  port_value: 5001

    进入容器内部强制更新文件

    # cd /etc/envoy
    # mv cds.yaml tmp
    # mv tmp cds.yaml

    调用api,发现在不重启Envoy的情况下,实现了配置信息的动态更新

    至此,我们已经通过Envoy的静态配置与文件动态配置实现了一个网关来代理我们的.NET程序

  • 相关阅读:
    解决Tomcat无法shutdown进程
    ConcurrentHashMap Put()操作示例代码
    Spring Data JPA
    JAVA CAS原理
    多线程
    多线程
    java 虚拟机--新生代与老年代GC
    TCP协议中的三次握手和四次挥手
    java中volatile关键字
    Java多线程
  • 原文地址:https://www.cnblogs.com/chenyishi/p/15478526.html
Copyright © 2020-2023  润新知