☰
Nginx应用与运维——Nginx在微服务架构中的应用(二)
2026/10/7 2:50:56 网站建设 项目流程

Nginx在微服务架构中的应用

    • 2、基于Nginx的微服务网关
      • 2.1、Nginx产品组件
      • 2.2、开源微服务网关Kong
        • 2.2.1、消费者
        • 2.2.2、消费者接口
        • 2.2.3、管理接口
        • 2.2.4、操作对象
      • 2.3、安装部署
      • 2.4、微服务网关应用

2、基于Nginx的微服务网关

Nginx作为资深的代理负载服务器,在微服务的全生态架构方案中动作还是比较慢的,其在服务网格及无服务器化方面还在不断提升。Nginx官方也提供了相应的产品组件,并在商业版本中提供了完整的微服务网关方案。在开源版本中,很多人都基于开源Nginx扩展版OpenResty实现了不同版本的微服务网关应用,本节将以已经商业化的开源微服务网关应用Kong为例,介绍Nginx在微服务网关中的应用。Kong仍处在活跃开发的状态中,其1.0以后的版本与早期版本有很大的不同,本章以最新版本1.3为例进行介绍。

2.1、Nginx产品组件

微服务为软件生产带来了变革,相对地,也推动了Nginx应用产品的发展,在应对微服务架构的解决方案中,Nginx产品组件中主要有如下3款产品。

  • (1)Nginx控制器
    Nginx控制器(Nginx Controller)是Nginx Plus的Web集中监控和管理平台,提供了丰富的监控图表,使用户可以轻松地监视应用程序的运行状况和性能。使用Nginx控制器可以通过Web界面直观地集中管理数百台Nginx Plus服务器,其建立在模块化的架构体系上,可管理Nginx Plus的所有功能,包括其作为负载均衡、API网关及作为ServiceMesh环境中的代理服务等功能。负载均衡模块负责负载功能的配置、验证和故障诊断,API模块允许用户定义、发布、保护、监视、分析API,计划推出的Service Mesh模块将简化用户从Kubernetes的Ingress模式到ServiceMesh体系结构的转变以应对数百个或数千个微服务的管理。
  • (2)交付网关
    Nginx将更注重成为其所代理后端的应用交付网关实现,作为各种应用的统一入口,实现访问入口路由、应用防火墙、内容缓存、负载均衡等功能。例如,成为微服务架构中的API网关或作为Kubernetes架构中的Ingress组件。
  • (3)Web应用服务器
    Nginx Unit是一个支持多种语言、可动态配置的开源Web应用服务器,当前已经支持的语言有Go、Node.js、Perl、PHP、Python、Ruby和Java。它于2018年推出,Nginx官方正积极推动该项目的发展,也将提供对更多语言的解析支持。例如它支持Java语言的版本正在测试中,可以使Java应用以Tomcat兼容的方式被添加进来实现代码解析。Nginx Unit提供了基于RESTful API的动态配置方法,简化了复杂的配置内容,标准化的JSON配置内容更便于阅读,对Web服务的配置变更均在内存中完成,无须中断服务。Nginx Unit的最终目标是为多种语言应用创建一个统一的运行平台,并使应用程序代码以安全、可靠及最佳性能的方式运行。Nginx Unit将应用运行的网络通信层与应用代码拆分,使应用代码可更专注于业务功能的实现,并能更方便地以Service Mesh方式作为微服务架构中的基础设施。

2.2、开源微服务网关Kong

Kong是一款开源的API平台,它是基于Nginx扩展版OpenResty的Lua应用,其将Nginx的配置解构成多个Lua应用模块,通过Lua应用实现了Nginx中各请求阶段的操作。Kong把Nginx操作的配置存储在外部数据库中,并提供了REST风格的管理接口,用户可以通过管理接口实现Kong所有功能的动态操作。Kong支持PostgreSQL和Cassandra两种数据库,可以通过数据库的主从同步或分布式部署实现配置数据的高可用,多台Kong服务器通过数据库共享配置数据,实现对多台Kong服务器的统一配置管理。Kong提供了基于Lua脚本实现的多种功能插件,在将用户请求转发给后端服务之前,用户可使用这些插件实现用户请求的认证、访问限流、链路跟踪、日志处理等各种操作。Kong是一个微服务网关平台,它作为微服务API的统一入口对外提供服务,为方便API的管理,定义了如下术语。

2.2.1、消费者

Kong系统中,把访问微服务API的用户定义为消费者,用户可以通过消费者对象定义消费者身份,并可通过相关插件实现消费者访问路由规则或服务的授权。

2.2.2、消费者接口

消费者接口是消费者访问微服务API的接口,用于实现后端被代理目标的访问转发。

2.2.3、管理接口

管理接口是进行Kong功能配置的接口,可通过管理接口对操作对象进行配置,其约定了REST风格的语法,用户可以很容易地通过管理接口实现对Kong的功能配置。

2.2.4、操作对象

Kong为方便实现Nginx配置的动态管理,定义了多个操作对象和对象参数,通过管理接口对不同的操作对象按照该对象的对象参数进行配置,可以非常快速地完成Kong的管理操作。Kong常用的操作对象有目标(target)对象、上游(upstream)对象、服务(service)对象、路由(route)对象、消费者(consumer)对象、插件(plugin)对象、证书(certificate)对象、CA证书(CA Certificate)对象、SNI对象。

目标对象和上游对象构成真实的被访问服务器集群,可通过上游对象实现目标对象的负载均衡、会话保持等配置。路由对象和服务对象构成了Nginx虚拟主机的访问入口路由和转发目标的配置,服务对象可以直接代理一个外部主机域名,也可以直接关联上游对象实现用户请求的转发。插件对象由不同的功能插件脚本组成,其可以与路由对象、服务对象及消费者对象关联,实现消费者对象请求转发给后端服务之前的各种功能操作。消费者对象用于描述客户端标识,通过认证及ACL插件可以对其进行访问认证和访问路由对象或服务对象的授权。证书对象、CA证书对象、SNI对象均用于SSL相关配置。

由于管理工具Konga基于管理接口提供了更加方便的Web化操作方式,这里为方便读者理解和操作,便直接使用Konga配置界面的对象参数介绍Kong的相关操作对象和对象参数。

  • (1)目标对象
    目标对象等同于Nginx配置中上游服务器的主机,一个上游对象可以关联多个目标对象,目标对象的配置是动态即时生效的。由于上游对象需要维护目标对象的变更记录,因此目标对象只能手动或通过管理接口DELETE方法设置权重为0。目标对象的对象参数说明如表所示。
  • (2)上游对象
    Kong的上游对象用于描述Nginx配置指令域upstream的配置内容,Kong支持对其所关联的目标对象进行主动或被动健康检测的设置。Kong为方便上游对象及其关联目标对象的管理,通过Lua脚本实现了加权轮询(round-robin)、一致性哈希(consistent-hashing)、最少连接(least-connections)负载均衡算法,默认为轮询。一个上游对象由多个目标对象组成,可以通过管理接口实现目标对象的动态变更。通常在一致性哈希算法和加权轮询负载策略下,目标对象数量的动态变化会引起负载策略的重新计算,虽然这种影响无法避免,但为了降低因负载算法重新计算产生的影响,Kong为每个上游对象定义了一个环平衡器(ring-balancer),每个环平衡器有预先定义好数量的插槽(slot),上游对象中的每个目标对象将根据其权重被分配到相应数量的插槽,当目标对象数量变化时,只需对部分目标对象重新分配插槽而不需要负载策略的重新计算。环平衡器只有在上游对象更改总插槽数时才会进行负载策略的重新计算,目标对象初始分配的插槽数官方建议至少为100个,当上游对象预期为8个时,即使初始时为两个目标也至少应将总插槽数定义为800。上游对象的对象参数说明如表所示。
  • (3)服务对象
    Kong中的服务(Service)对象是指被代理的服务目标,既可以是一个域名,也可以是一个上游对象的名称,区别在于是否由Kong实现负载均衡。每个服务对象可以关联多个路由对象。一个服务对象只能关联一个上游对象或被代理的主机域名。服务对象的对象参数说明如表所示。
  • (4)路由对象
    路由(Route)对象用于表示Nginx配置中虚拟主机的配置,对应Nginx的指令域Server及其包含的location配置。Kong配置结构中,因为服务对象用于关联被代理的目标,而路由对象单独存在没有意义,所以其必须与服务对象关联使用。路由对象的对象参数说明如表所示。

  • (5)插件对象
    插件对象用于对用户在消费接口的请求/响应闭环中的不同插件执行方法进行配置,不同的插件与路由对象、服务对象及消费者对象关联,实现对消费者对象在Nginx中各请求阶段的相关操作。Kong的插件对象既可以关联到服务对象,实现所有该服务的请求控制,也可以关联到路由对象,仅对某些路由接口的请求进行控制,甚至是更细粒度的,仅对指定的消费者进行控制。一个插件在一个请求的生命周期中只运行一次,当一个插件被与多个操作对象关联时,与路由对象、服务对象及消费者对象这3个对象关联的越具体则执行优先级最高,插件的全局配置优先级最低。
  • (6)消费者对象
    消费者对象是描述用户身份的对象,通过认证及ACL插件可以对其进行访问认证和访问路由对象或服务对象的授权。
  • (7)证书对象
    证书对象表示HTTPS域名关联的证书,证书对象用于存储SSL证书的公共证书/私钥对。Kong使用这些对象来处理加密请求的SSL终止。
  • (8)CA证书对象
    CA证书对象表示受信任的CA。Kong使用这些对象来验证客户端或服务器证书的有效性。
  • (9)SNI对象
    Kong的SNI(Server Name Indication)对象可与证书对象进行关联,将证书/密钥对绑定到一个或多个域名。SNI是一种改善SSL/TLS的技术,用于对客户端请头中Host字段进行处理,通过对Host字段的识别解决了当一个服务器绑定多个域名时SSL证书选择的问题,服务器将根据Host字段的域名返回该域名的SSL证书。

2.3、安装部署

Kong可以灵活地部署在用户的局域网中,其同样支持多种部署方式,官方在DockerHub上提供了Docker镜像,方便用户快速实现Kong的Docker化部署。部署步骤如下。

  • (1)首先初始化系统环境并安装Docker应用,配置样例如下:

    # 安装yum工具yuminstall-yyum-utils# 安装Docker官方yum源yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo# 安装Docker及docker-compose应用yuminstall-ydocker-cedocker-compose# 设置Docker服务开机自启动systemctlenabledocker# 启动Docker服务systemctl startdocker
  • (2)Kong应用部署
    Kong将Nginx的配置存储在外部数据库,可以通过自带的数据库初始化命令自动完成数据库表结构的创建和初始数据的添加,为方便一次性创建,该脚本会启动独立的容器kong-migrations来完成此项操作。此处脚本创建的Kong规划为主管理服务器,管理接口不提供外部访问,仅提供在同一虚拟网络内的Web工具的访问,因此设置为固定IP。Docker-compose脚本内容如下:

    version:'2.1'# 创建名为kong-net的虚拟网络networks: kong-net: ipam: config: - subnet:172.19.0.0/24 gateway:172.19.0.1 name: kong-net services:# 创建用于数据库初始化的独立容器kong-migrations: hostname: kong-migrations container_name: kong-migrations image: kong:latest command: kong migrations bootstrap depends_on: db: condition: service_healthy env_file: - .env_kong links: - db:db networks: - kong-net restart: on-failure# 创建Kong容器kong: hostname: kong-nginx container_name: kong-nginx image: kong:latest depends_on: db: condition: service_healthy env_file: - .env_kong networks: kong-net: ipv4_address:172.19.0.201 ports: -"8000:8000/tcp"# 用于监听HTTP协议的消费接口,实现用户请求的接入# - "8001:8001/tcp" # 用于监听HTTP协议的管理接口,此处关闭外部访问-"8443:8443/tcp"# 用于监听HTTPS协议的消费接口,实现用户请求的接入# - "8444:8444/tcp" # 用于监听HTTPS协议的管理接口,此处关闭外部访问# network_mode: host # 在高并发应用场景下,可以将Docker容器以host模式运行,# 提高传输效率healthcheck: test:["CMD","kong","health"]interval: 10s timeout: 10s retries:10restart: on-failure# 创建Kong的postgreSQL数据库容器db: hostname: kong-postgres container_name: kong-postgres image: postgres:9.5 env_file: - .env_postgress healthcheck: test:["CMD","pg_isready","-U","kong"]interval: 30s timeout: 30s retries:3restart: on-failure stdin_open:truetty:truenetworks: - kong-net ipv4_address:172.19.0.202 volumes: - /opt/data/apps/kong/postgresql/data:/var/lib/postgresql/data

    环境变量文件内容如下:

    cat>.env_kong<<EOF KONG_ADMIN_ACCESS_LOG=/dev/stdout KONG_ADMIN_ERROR_LOG=/dev/stderr KONG_ADMIN_LISTEN=0.0.0.0:8001 KONG_CASSANDRA_CONTACT_POINTS=db KONG_PROXY_ACCESS_LOG=/dev/stdout KONG_PROXY_ERROR_LOG=/dev/stderr KONG_DATABASE=postgres KONG_PG_DATABASE=kong-data KONG_PG_HOST=db KONG_PG_PASSWORD=kong KONG_PG_USER=kong EOFcat>.env_postgress<<EOF POSTGRES_DB=kong-data POSTGRES_PASSWORD=kong POSTGRES_USER=kong EOF
  • (3)Kong的Web管理工具Konga
    Konga是基于Node.js开发的Kong开源管理工具,它不仅提供了Kong管理接口的全部操作对象的管理功能,同时还可以对多个Kong节点进行管理,包括Kong节点的备份、还原、健康监测等,还提供了多用户的功能,让Kong的日常管理操作可以更加方便灵活。

    Konga通过数据存储操作用户及Kong管理相关的配置,此处与Kong共用PostgreSQL数据库,可通过如下命令创建并初始化数据库实例konga:

    dockerrun--networkkong-net--rmpantsel/konga-cprepare-apostgres-upostgresql://kong:kong@172.19.0.202:5432/konga

    编写docker-compose脚本,脚本内容如下:

    version:'2.1'services:# 创建konga容器konga: hostname: konga container_name: konga image: pantsel/konga env_file: - .env_konga external_links: - kong-postgres:db ports: -"1337:1337/tcp"networks: - kong-net# 加入名为kong-net的虚拟网络networks: kong-net: external:truename: kong-net

    环境变量文件内容如下:

    cat>.env_konga<<EOF DB_ADAPTER=postgres DB_HOST=db DB_USER=kong DB_PASSWORD=kong DB_DATABASE=konga NODE_ENV=production EOF

    Kong集群只需在其他服务器部署Kong节点并连接到同一个PostgreSQL数据库即可,Kong为避免频繁地进行数据库连接,会将数据库的内容缓存在本机内存中,管理接口修改数据库配置后,Kong的配置会在同步周期下一次开始时生效,同步周期可以通过配置文件kong.conf中的配置参数db_update_frequency进行修改,默认时间为5秒。

2.4、微服务网关应用

作为一款微服务网关应用,Kong通过插件功能实现了微服务网关的多种功能,此处分别以访问认证、请求终止、数据整形为例,为了方便读者理解和应用,此处均使用管理接口直接操作,功能参数仍以Konga页面显示的名称进行说明。

  • (1)访问认证
    Kong提供了基本认证、密钥认证、OAuth2认证、HMAC认证、JWT认证、LDAP认证等多种方式的认证插件,此处列举常见的密钥认证方式配置。密钥认证插件参数说明如表所示。

    接口认证是服务开发中常见的功能,Kong插件的认证功能可以让开发工程师不必单独开发此功能,仅需选择使用Kong的认证机制或通过认证转发使用内部的认证服务器,让所有的接口服务很容易地实现统一认证的功能。在下面的配置样例中,在Konga中按照参数配置添加密钥认证插件,认证密钥名称为apikey。
    # 创建服务curl-i-XPOST\--urlhttp://10.10.4.8:8001/services/\--data'name=baidu'\--data'url=https://www.baidu.com'# 创建路由curl-i-XPOST\--urlhttp://10.10.4.8:8001/services/baidu/routes\--data'name=baidu'\--data'paths[]=/v1/baidu'# 访问测试,确认路由规则curl-i-XGET\--urlhttp://10.10.4.8:8000/v1/baidu# 关联插件到路由对象实例baiducurl-i-XPOST\--urlhttp://10.10.4.8:8001/routes/baidu/plugins\--data"name=key-auth"\--data"config.key_names=apikey"\# 创建消费者curl-d"username=test123"http://10.10.4.8:8001/consumers/# 创建消费者密钥curl-XPOST http://10.10.4.8:8001/consumers/test123/key-auth-d''# 查看并获得密钥curlhttp://10.10.4.8:8001/consumers/test123/key-auth# 消费者使用密钥访问curl-i-XGET\--urlhttp://10.10.4.8:8000\--header"apikey: xKgpAM6qBQE3e8nrR51dIrK89ggRdelf"
  • (2)请求终止
    请求终止(request-termination)插件原设计场景是进行请求熔断等安全管理,但其同样适用于做依赖该接口的测试桩场景,通过Kong的请求终止插件可以非常快速地实现该功能,而且不需要做任何代码改动,测试桩的创建和撤销也非常简单。插件参数说明如表所示。

    下面是一个测试桩的样例,该插件可以对当前接口的请求返回固定格式的JSON数据,该场景可以满足不同团队合作时在真实业务API代码开发完毕前,让合作方、前端及测试人员进行代码升级或测试。
    # 创建服务curl-i-XPOST\--urlhttp://10.10.4.8:8001/services/\--data'name=baidu'\--data'url=https://www.baidu.com'# 创建路由curl-i-XPOST\--urlhttp://10.10.4.8:8001/services/baidu/routes\--data'name=baidu2'\--data'paths[]=/v2/baidu'# 访问测试,确认路由规则curl-i-XGET\--urlhttp://10.10.4.8:8000/v2/baidu# 关联插件到路由对象实例baiducurl-i-XPOST\--urlhttp://10.10.4.8:8001/routes/baidu2/plugins\--data"name=request-termination"\--data"config.status_code=200"\--data"config.content_type=application/json; charset=utf-8"\--data"config.body={\"status\": 200,\"data\": {\"status_code\": 403,\"message\":\"测试数据\"},\"message\":\"专业测试桩\"}"# 测试结果curl-i-XGET\--urlhttp://10.10.4.8:8000/v2/baidu
  • (3)数据整形
    通常一套服务提供的JSON格式数据是固定的,但在多个团队的开发合作中,可能需要对接口数据返回格式有不同的需求,以往大家都希望用一个统一的标准进行规范化的JSON数据格式输出,但执行起来则会遇到诸多现实问题。通过Kong的插件可以让使用方和供给方不必再为这种标准而纠结,开发人员不需要修改代码,仅需要简单进行Lua脚本编写就可以实现现有服务的供给或使用需求,这里使用Kong的第三方插件API转换(API Transformer)插件做样例在中间进行数据整形,大家也可以根据实际需求定制自己的Kong插件。API转换插件功能参数如表所示。

    此处演示将管理接口返回的JSON数据格式修改为前端jQuery插件DataTables的数据格式。因API转换插件的request_transformer参数为必选项,即便不需要请求阶段数据整形,也要为此参数指定文件,如下样例中将创建一个返回空数据的req.lua文件。
    # 安装插件gitclone https://github.com/qnap-dev/kong-plugin-api-transformer.gitcdkong-plugin-api-transformer luarocksmake# 启用插件,需要重启Kong才可生效sed-i"/\"session\",/a\\"api-transformer\""/usr/local/share/lua/5.1/kong/constants.lua# 创建服务,代理目标为管理接口curl-i-XPOST\--urlhttp://10.10.4.8:8001/services/\--data'name=adminapi'\--data'url=http://10.10.4.8:8001'# 创建路由curl-i-XPOST\--urlhttp://10.10.4.8:8001/services/adminapi/routes\--data'name=adminapi'\--data'paths[]=/adminapi'# 访问测试,确认路由策略curl-i-XGET\--urlhttp://10.10.4.8:8000/adminapi# 关联插件到路由adminapicurl-XPOST http://10.10.4.8:8001/routes/adminapi/plugins\--data"name=api-transformer"\--data"config.request_transformer=/etc/kong/scripts/req.lua"\--data"config.response_transformer=/etc/kong/scripts/datatables.lua"\--data"config.http_200_always=true"# 创建req.lua,此处需要在Kong系统中进行操作mkdir-p/etc/kong/scriptsecho"return true,\"\"">/etc/kong/scripts/req.lua# 创建响应数据整形脚本datatables.lua,此处需要在Kong系统中进行操作cat>/etc/kong/scripts/datatables.lua<<EOF local return_body = { data = {} } local _resp_json_body = ngx.ctx.resp_json_body return_body.data = _resp_json_body.data local i = 0; for _, obj in pairs(return_body.data) do # 此处可进行相关字段的变更或过滤 i = i + 1; end return_body["page_size"] = i return_body["recordsFiltered"] = i return_body["recordsTotal"] = i return true, _cjson_encode_(return_body) EOF# 访问测试,确认返回数据curl-i-XGET\--urlhttp://10.10.4.8:8000/adminapi/routes
    Kong的插件都是基于Lua脚本实现的,通过Nginx可以实现用户请求过程中各阶段的数据操作,此处不再举例,大家可以根据实际需求灵活使用Kong的功能。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询