https://github.com/fossilman/Kong-In-Action
问题领域 | 描述 | 影响 |
---|---|---|
系统架构 | 网关层作为流量中枢,对系统稳定性至关重要 | 网关层不稳定或宕机可导致整个系统不可用 |
微服务架构实践 | 微服务架构要求网关层支持技术栈变迁和服务聚合 | 缺乏网关层支持会限制微服务架构的实施和效能 |
安全性与运维 | 网关层需处理加解密、鉴权、黑白名单等安全需求 | 更新网关层代码时,不影响生产环境流量是一大挑战 |
微服务独立功能 | 微服务架构导致需在多个小应用中实现通用功能 | 缺乏统一的底层架构导致重复劳动和高研发成本 |
Kong、OpenResty都是基于Nginx打造的新一代服务器。它们兼具Web服务器的功能,但侧重于网关层特性的延伸
图1-3 Kong、OpenResty与Nginx的关系
图1-7 Kong服务器架构
在Mac环境中安装Kong网关
安装Homebrew,如果已经安装请忽略
$ ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)" $ brew tap kong/kong$ brew install kong
安装完成后,我们还需要准备两个配置文件,一个是启动项配置文件。用户可以从https://raw.githubusercontent.com/Kong/kong/master/kong.conf.default下载配置模块,并更改配置文件名为kong.conf。修改kong.conf配置文件内容如代码清单1-1所示。
代码清单1-1 kong.conf配置文件
另一个是kong.yml文件,需要使用kong config init命令生成。该配置文件内容可以为空,但文件本身不可缺失。当一切准备就绪后,使用kong start-c kong.conf命令启动Kong服务,在浏览器中输入http://127.0.0.1:8001可以查看服务是否启动成功,效果如图1-9所示。
图1-9 Kong服务启动页面
在Docker环境中安装Kong网关
程序清单1-2 安装Kong网关
$ docker network create kong-net$ docker run -d --name kong-database \ --network=kong-net \ -p 5432:5432 \ -e "POSTGRES_USER=kong" \ -e "POSTGRES_DB=kong" \ -e "POSTGRES_PASSWORD=kong" \ postgres:9.6$ docker run --rm \ --network=kong-net \ -e "KONG_DATABASE=postgres" \ -e "KONG_PG_HOST=kong-database" \ -e "KONG_PG_USER=kong" \ -e "KONG_PG_PASSWORD=kong" \ -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ kong:2.0.5 kong migrations bootstrap$ docker run -d --name kong \ --network=kong-net \ -e "KONG_DATABASE=postgres" \ -e "KONG_PG_HOST=kong-database" \ -e "KONG_PG_USER=kong" \ -e "KONG_PG_PASSWORD=kong" \ -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ -p 8000:8000 \ -p 8443:8443 \ -p 8001:8001 \ -p 8444:8444 \ kong:2.0.5
程序清单1-6 docker-compose.yml启动文件
29 ...30 ...31 kong:32 build:33 context: ./kong-gateway34 container_name: kong35 environment:36 KONG_DATABASE: 'off'37 KONG_DECLARATIVE_CONFIG: /usr/local/kong/declarative/config.yml38 KONG_PROXY_ACCESS_LOG: /dev/stdout39 KONG_ADMIN_ACCESS_LOG: /dev/stdout40 KONG_PROXY_ERROR_LOG: /dev/stderr41 KONG_ADMIN_ERROR_LOG: /dev/stderr42 KONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl43 ports:44 - '8000:8000'45 - '8443:8443'46 - '8001:8001'47 - '8444:8444'48 volumes:49 - ./kong-gateway:/usr/local/kong/declarative50 depends_on:51 - backend
Dockerfile配置文件如下。
1 # kong dockerfile2 FROM kong:2.0.5
在云原生热度持续火热的当下,Nginx赖以生存的高并发、高性能壁垒已开始出现松动。灵活性、易用性、系统伸缩性以及可高度定制化,这些特性变得越来越重要。Kong网关正是在这种市场需求下应运而生的。
程序设计语言中的一等、二等、三等公民。
函数为“一等公民”是函数式编程的基础。
公民类别 | 作为参数传递 | 从子程序中返回 | 赋值给变量 |
---|---|---|---|
一等公民 | 可以 | 可以 | 可以 |
二等公民 | 可以 | 不能 | 不能 |
三等公民 | 不能 | 不能 | 不能 |
md2pod.pl:主要用于将GitHub风格的Markdown格式文档转换为Perl的POD格式文档。代码清单4-1展示了它的基本用法。
常见的火焰图类型有on-CPU、of f-CPU、Memory、Hot/Cold和Differential等。关于火焰图详细的介绍,读者可以参考Blazing Performance with Flame Graphs。on-CPU火焰图或者off-CPU火焰图的使用场景取决于当前的瓶颈。如果瓶颈是CPU,则使用on-CPU火焰图;如果瓶颈是I/O或锁,则使用off-CPU火焰图。如果瓶颈无法确定,可以通过压测工具来确认。通过压测工具观察能否让CPU使用率趋于饱和,如果能,则使用on-CPU火焰图;如果不能,则使用of f-CPU火焰图。
火焰图的生成主要依赖于SystemTap工具
火焰图类型 | 使用场景 | 瓶颈指示 | 额外信息 |
---|---|---|---|
on-CPU | 当瓶颈是CPU时 | CPU利用率高 | 适用于CPU饱和场景,依赖于SystemTap工具 |
off-CPU | 当瓶颈是I/O或锁时 | I/O或锁等待时间长 | 适用于CPU未饱和但性能受限场景,依赖于SystemTap工具 |
Kong网关可分为三种部署方式:无数据库部署模式、数据库部署模式和混合部署模式。
无数据库部署模式中,Kong网关使用特定的配置文件进行部署。配置文件的格式为yaml,通常以yml后缀结尾。用户可以在启动项配置中使用declarative_config指定该文件路径。需要注意的是,使用该配置文件的前提条件是database配置项设置为of f。
1)首先创建一个Docker网络,名称为kong-net,网络模式为bridge模式。
2)预先准备声明性配置文件kong.yml,此处我们使用的是官方提供的模板文件。
程序清单5-7 kong.yml文件
表5-9 元数据配置文件配置项
程序清单5-9 2.3.4节中的kong.yml配置文件
从使用场景来说,PostgreSQL偏向于单点模式,Cassandra可在集群模式下使用。
混合部署模式是在Kong 2.0版本中新引入的一种部署方式,也可以称为控制平面/数据平面分离部署。控制平面(Control Plane,CP)功能类似于Admin API,用于管理配置。数据平面(Data Plane,DP)用于为代理提供流量。每个DP节点都会连接到CP节点。DP节点摒弃了传统的通信方式,不直接与数据库连接,而是与CP进行交互,并接收最新的配置项
图5-3 混合部署模式架构
使用Admin API为Kong网关添加代理配置,步骤如下。 1)创建一个名为demo的上游服务:
$ curl -X POST http://127.0.0.1:8001/upstreams \ --data "name=demo"
2)为上游服务绑定一个target,代理到www.baidu.com地址:
$ curl -X POST http://127.0.0.1:8001/upstreams/demo/targets \ --data "target=www.baidu.com:80" \ --data "weight=100"
3)创建一个名为service_demo的服务,host属性与之前创建的上游服务对应:
$ curl -X POST http://127.0.0.1:8001/services \ --data "name=service_demo" \ --data "host=demo"
4)创建一个名为route_demo的路由,匹配路径为/baidu:
$ curl -X POST http://127.0.0.1:8001/services/service_demo/routes \ --data "paths[]=/baidu" \ --data "name=route_demo"
5)验证代理是否生效:
$ curl 127.0.0.1:8000/baidu
...百度一下,你就知道...
步骤 | 操作 | 描述 |
---|---|---|
1 | 创建上游服务 | 使用curl命令创建名为demo的上游服务 |
2 | 绑定Target | 将www.baidu.com作为目标绑定到demo服务上 |
3 | 创建服务 | 创建一个名为service_demo的服务,其host属性对应于之前创建的上游服务 |
4 | 创建路由 | 创建名为route_demo的路由,匹配路径为/baidu |
5 | 验证代理 | 使用curl命令验证代理配置是否已生效 |
Kong网关可以划分为三种代理模式。这三种代理模式是互斥的,各模式之间支持的可配置属性也存在差异
表7-1 三种代理模式信息
Kong网关还支持使用正则表达式进行模糊匹配。这个功能在实际场景中非常实用。
Paths属性匹配优先级
1)普通前缀路径遵守最长前缀路径匹配规则,即/version/any/优先级高于/version。 2)正则表达式根据路由的regex_priority属性从最高优先级到最低优先级进行评估。同优先级的正则表达式也遵守最长前缀路径匹配规则。 3)正则表达式的匹配优先级始终高于前缀路径表达式。
匹配类型 | 优先级规则 | 描述 |
---|---|---|
普通前缀路径 | 最长前缀路径优先 | 如/version/any/的优先级高于/version |
正则表达式 | 根据regex_priority属性评估 | 同优先级的正则表达式遵守最长前缀路径匹配规则 |
正则表达式 vs. 前缀路径 | 正则表达式优先级高于前缀路径 | 正则表达式匹配优先于前缀路径表达式 |
sources & destinations属性仅适用于TCP和TLS路由。它们允许通过传入的IP地址和端口号列表来匹配路由。两个属性的不同点在于一个是匹配源地址,一个是匹配目标地址。我们来看一个示例:
{ "protocols": ["tcp", "tls"], "sources": [{"ip":"10.1.0.0/16", "port":1234}, {"ip":"10.2.2.2"}, {"port":9123}], "id": "...",}
路由会匹配源地址是10.1.0.0/16(CIDR范围中的IP),或者IP地址是10.2.2.2,抑或者端口号为9123的TCP或TLS连接。
特性 | 描述 | 注意事项 |
---|---|---|
SNI路由匹配 | 当使用安全协议,snis属性可以作为路由属性。例如,TLS连接的SNI扩展名匹配snis字段时,请求匹配该路由 | SNI指示不能在TLS连接建立后修改 |
多SNI支持 | snis属性中可以指定多个SNI,匹配任何一个即可满足路由条件,实现“或”关系 | 虽然理论上可以随意配置snis和hosts属性,但通常不推荐这样做 |
SNI的重要性 | SNI在TLS握手期间指示要连接的服务器,支持多个SSL证书安全托管在同一IP地址上 | 使用SNI时,每个HTTPS网站可以拥有独立的TLS证书,即使网站共享IP地址 |
当使用安全协议时(HTTPS、gRPC或TLS),用户可以将snis当作路由属性。示例如下:
{ "snis": ["foo.test", "example.com"], "id": "..."}
在TLS连接的SNI扩展名中设置的主机名若能匹配snis属性中的字段,则该请求可以匹配此路由。如前所述,SNI路由不仅适用于TLS,还适用于TLS上承载的其他协议,例如HTTPS。如果在snis属性中指定多个SNI,仅需匹配其中任何一个即可,名称之间匹配满足“或”关系。 SNI指示在TLS握手期间要连接的服务器,并且在建立TLS连接后无法修改。这意味着在执行路由匹配时,无论请求头中host字段是什么,复用相同keepalive连接的多个请求将具有相同的SNI主机名。理论上,用户可以随便配置路由的snis属性和hosts属性,但通常情况下不推荐这么操作。 注意 SNI(server Name Indication,服务器名称指示)指示在握手期间浏览器正在联系的主机名,允许服务器为多个网站安全地托管多个SSL证书。多个网站存在于同一IP地址上。使用SNI时,服务器的主机名包含在TLS握手中,这使得HTTPS网站具有唯一的TLS证书(即使网站共享IP地址)。
步骤 | 操作 | 描述 |
---|---|---|
1 | 创建服务 | 添加名为example-service的服务,代理到http://mockbin.org/request |
2 | 添加路由 | 为example-service服务添加路由,访问路径为/auth-sample |
3 | 验证配置 | 使用curl命令检查服务和路由配置是否成功 |
4 | 添加鉴权插件 | 为example-service服务添加名为key-auth的鉴权插件 |
5 | 验证鉴权插件 | 验证鉴权插件是否成功应用,检查无key时是否返回错误 |
6 | 创建消费者实体 | 添加消费者,用户名为user123,自定义ID为SOME_CUSTOM_ID |
7 | 提供身份验证凭据 | 为user123消费者配置新的凭证,并使用该凭证进行身份验证测试 |
消费者的核心原则是用户可以将插件附加在其之上,从而定制请求行为。 注意 理解消费者的最简单方法就是将它们一对一映射到具体用户。然而,对于Kong网关来说,这个理解过于狭隘。例如开发者有多个应用,他可以为每个应用及其版本定义一个消费者,或者为每个平台定义一个消费者,例如AndroidConsumer、IOSConsumer等。
最常见的鉴权是对服务进行身份校验,并且不允许任何未经身份验证的请求通过。鉴权插件的通用方案如下。 1)配置服务和路由实体,验证代理请求是否通过。 ①添加一个名为example-service的服务,并代理到http://mockbin.org/request,修改地址为Kong官方给出的示例地址:
$ curl -i -X POST \ --url http://127.0.0.1:8001/services/ \ --data 'name=example-service' \ --data 'url=http://mockbin.org/request'
②为该服务添加一个路由,访问路径为/auth-sample:
$ curl -i -X POST \ --url http://127.0.0.1:8001/services/example-service/routes \ --data 'paths[]=/auth-sample'
③使用curl命令验证上述配置是否成功:
$ curl http://127.0.0.1:8000/auth-sample{ "startedDateTime": "2020-09-25T00:34:45.620Z", "clientIPAddress": "162.20.0.1", "method": "GET", "url": "http://127.0.0.1/request", "httpVersion": "HTTP/1.1", "cookies": {}, "headers": { "host": "mockbin.org", "connection": "close", "x-forwarded-for": "162.20.0.1, 10.102.78.77, 3.12.247.135", "x-forwarded-proto": "http", "x-forwarded-host": "127.0.0.1", "x-forwarded-port": "80", "x-real-ip": "47.75.63.6", "user-agent": "curl/7.64.1", ...
2)将鉴权插件作用于服务实体或者全局。 ①为services添加名为key-auto的鉴权插件:
$ curl -X POST 127.0.0.1:8001/services/example-service/plugins \ --data "name=key-auth"
②验证该鉴权插件是否添加成功,如果添加成功,但是没有key,返回结果会报错;如果没有添加成功,则正常返回。
$ curl http://127.0.0.1:8000/auth-sample{"message":"No API key found in request"}
3)创建一个消费者实体。 添加一个消费者,username为user123,custom_id为SOME_CUSTOM_ID:
$ curl -d "username=user123&custom_id=SOME_CUSTOM_ID" http://127.0.0.1:8001/consumers/
4)为消费者提供特定身份验证方法的身份验证凭据。 ①为该消费者配置新的凭证:
$ curl -X POST http://127.0.0.1:8001/consumers/user123/key-auth -d ''{ "created_at":1600994689,"consumer":{"id":"d833db4e-4eae-4575-947e- d7c2f61bb299"}, "id":"bb499039-e071-4419-9c00-5bd8af17a5f7", "tags":null, "ttl":null, "key":"joWSLkrBQUgXT2darCwZGjVxBFPUHljs"}
②将上述消费者中的key作为url的querystring参数并发出请求:
$ curl http://127.0.0.1:8000/auth-sample?apikey=joWSLkrBQUgXT2darCwZGjVxBFPUHljs{ "startedDateTime": "2020-09-25T00:46:01.856Z", "clientIPAddress": "162.20.0.1", "method": "GET", "url": "http://127.0.0.1/request?apikey=joWSLkrBQUgXT2darCwZGjVxBFPUHljs", "httpVersion": "HTTP/1.1", "cookies": {}, ... "queryString": { "apikey": "joWSLkrBQUgXT2darCwZGjVxBFPUHljs" },...
匿名接入流程 从上述的例子我们发现,当添加key-auth鉴权插件后,请求必须带上凭据才能访问通过。接下来我们看一下如何配置匿名用户直接访问代理服务。 1)紧接上述流程添加一个名为anonymous_users的匿名用户:
$ curl -i -X POST \ --url http://127.0.0.1:8001/consumers/ \ --data "username=anonymous_users"
2)配置key-auth鉴权插件允许匿名用户访问:
$ curl 127.0.0.1:8001/services/example-service/plugins{"next":null,"data":..."id":"16276239-c173-48d5-82c7-171e01d8fb5f",...}
$ curl http://127.0.0.1:8001/consumers/anonymous_users{..."id":"19a20edc-ade4-45ff-8201-259c542727d3",...}
$ curl -i -X PATCH \ --url http://localhost:8001/plugins/16276239-c173-48d5-82c7-171e01d8fb 5f \ --data "config.anonymous=19a20edc-ade4-45ff-8201-259c542727d3"
3)使用curl命令验证是否可以直接访问:
$ curl -X GET \ --url http://localhost:8000/auth-sample{ "startedDateTime": "2020-09-25T01:03:23.809Z", "clientIPAddress": "162.20.0.1", "method": "GET", "url": "http://127.0.0.1/request", "httpVersion": "HTTP/1.1", "cookies": {},... "x-consumer-id": "19a20edc-ade4-45ff-8201-259c542727d3", "x-consumer-username": "anonymous_users", "x-anonymous-consumer": "true",... "queryString": {},...
Kong网关能够配置服务,同时允许身份验证和匿名访问。比如用户可以对某个服务开设匿名用户访问权限,但是限流策略比较严格;同时对该服务增加一个需要身份验证的访问权限,并放宽限流策略。
多重认证策略 Kong网关支持给服务配置多个鉴权插件,允许不同客户端使用不同的身份验证策略来访问指定的服务或路由。在评估多个身份验证凭据时,逻辑比较复杂,关键因素在于config.anonymous属性。
多重认证策略补充说明如下。
特性 | 未设置config.anonymous | 设置config.anonymous | 补充说明 |
---|---|---|---|
鉴权执行 | 每个插件总是执行身份验证 | 仅上一个鉴权条件失败时执行下一个鉴权插件 | 统一配置匿名访问权限,避免不确定的鉴权结果 |
验证结果逻辑 | 身份验证结果取“与”关系 | 身份验证结果取“或”关系 | “与”关系时,最后一个插件的凭据信息接入上游;“或”关系时,第一个成功的或最后一个匿名消费者的信息接入 |
认证失败行为 | 返回40XX错误 | 将请求作为匿名消费者处理,不返回4XX | 注意匿名访问权限的配置对整体鉴权逻辑的影响 |
市场上较为成熟的软件负载均衡解决方案为Nginx、HAProxy和LVS;硬件负载均衡解决方案为F5、A10等。 软硬件负载均衡解决方案各有优缺点。我们可以横向对比一下F5和Nginx这两种常用解决方案,如表8-1所示。
表8-1 F5与Nginx优缺点
Kong网关在Nginx负载均衡策略基础上做了更高的抽象。从功能特性上划分,其可以分为两种实现方式:
DNS记录类型 | 描述 | DNS记录优先级 |
---|---|---|
A记录 | 指定主机名(或域名)对应的IPv4 IP地址记录 | 3 |
AAAA记录 | 将域名解析到指定的IPv6 IP地址 | 同A记录 |
CNAME记录 | 别名解析,可以将不同域名转到一个域名记录上 | 4 |
SRV记录 | 指定服务地址,包括服务器的地址、端口、优先级和权重 | 2 |
DNS记录类型
DNS记录优先级
响应类型 | 影响 | 计数器更新 | 健康状态影响 |
---|---|---|---|
状态码为healthy | 递增successes计数器 | 清零其他计数器 | 如果successes计数器达到阈值,服务标记为健康 |
连接失败 | 递增tcp failure计数器 | 清零successes计数器 | 如果tcp failures达到阈值,服务标记为不健康 |
发生超时 | 递增timeouts计数器 | 清零successes计数器 | 如果timeouts达到阈值,服务标记为不健康 |
状态码为unhealthy | 递增http failure计数器 | 清零successes计数器 | 如果http failures达到阈值,服务标记为不健康 |
处理完一个请求可能会返回TCP错误、超时或者http状态码等信息。根据这些信息,系统内部会实时更新一系列内部计数器。
Kong网关中的健康检查方式包括主动健康检查和被动健康检查。
特征 | 主动健康检查 | 被动健康检查 |
---|---|---|
描述 | 定期请求后端服务的特定http/https端点,根据响应确定健康状态 | 根据流量中的响应行为判断后端服务的健康状态 |
优点 | 可自动重新启用恢复健康的后端服务;允许自定义健康检查指标 | 不产生额外流量;无需额外配置 |
缺点 | 产生额外流量;需要后端服务配置特定端点 | 恢复健康的后端服务不会自动重新启用 |
Kong网关插件内容 | 描述 | 组件 |
---|---|---|
插件简介 | Kong网关是一个加载和执行Lua模块的Lua应用程序,插件通过PDK与HTTP请求、响应或流交互 | - |
自定义插件 | 自定义插件遵循特定命名规范,需在配置文件中指定插件名称以被加载 | kong.plugins.<plugin-name> |
基本插件模块 | 插件至少包含handler.lua和schema.lua两个模块,分别用于定义插件的接口和配置项规则 | handler.lua, schema.lua |
高级插件模块 | 高级插件模块包括额外功能,如定义数据库业务数据表、在Admin API中暴露端点等 | api.lua, daos.lua, migrations, handler.lua, schema.lua |
Kong网关就是一个Lua应用程序。它的主要功能就是加载和执行Lua模块(这里我们抽象成了插件),并为它们提供整个开发环境,包括SDK、数据库抽象、数据迁移等。 插件是由Lua模块组成的,它们通过插件开发包(Plugin Development Kit,PDK)与HTTP请求、响应或者流进行交互,然后实现各种逻辑。PDK也是一组Lua方法。插件可以通过它们与Kong服务器的核心组件进行交互。
Kong插件中的Lua脚本遵循同一个命名规范。Kong网关会检测符合命令规范的Lua文件并加载它们。命名规范如下所示: kong.plugins..
为了让Kong网关明确需要去查找哪些自定义插件,用户需要在配置文件的plugins属性中添加插件名称字段。多个插件之间使用逗号隔开,例如:
plugins = bundled,my-custom-plugin # 用户自定义插件名
当用户不希望加载任何系统自带的插件时,可以在plugins属性中添加自定义的插件名:
plugins = my-custom-plugin # 用户自定义插件名
现在,Kong网关会尝试从以下命名空间加载多个Lua模块:
kong.plugins.my-custom-plugin.
其中,有些模块是必需的(例如handler模块),有些是可选的,以便实现一些额外功能。下面我们会详细描述基本插件模块以及它们的用途。
基本插件模块 插件必须包含两个模块,目录结构如下:
simple-plugin├── handler.lua└── schema.lua
·handler模块:插件的核心模块。它提供了一组接口,需要用户自定义实现,其中每个方法都会在请求和连接生命周期中的指定时间点运行。 ·schema模块:该模块定义了配置项的规则和格式,会对用户输入的数据进行校验。
高级插件模块 有些插件与Kong网关集成得很深,比如需要在数据库中定义业务数据表,或者在Admin API中暴露新的端点等。插件可以通过添加新的模块来完成这些功能。一个插件包括所有的可选模块(除基本模块之外,还有高级模块),其目录结构如下:
complete-plugin├── api.lua├── daos.lua├── handler.lua├── migrations│ ├── cassandra.lua│ └── postgres.lua└── schema.lua
表9-15 插件模块
优化对象 | 优化层面 | 优化策略 | 详细描述 |
---|---|---|---|
Elasticsearch | 索引层面 | 增加刷新时间间隔 | 延长刷新时间间隔以减少段合并压力 |
调整副本数量 | 增加副本数量提高可用性,但影响写入效率 | ||
开启异步刷写 | 允许微量日志数据丢失来提升性能 | ||
开启慢查询日志 | 用于排查问题的慢查询日志 | ||
服务器层面 | 内存调优 | 平衡Lucene和Elasticsearch内存占比,禁止Swap分区 | |
调整集群分片 | 分片容量和数目调整 | ||
Mapping建模和查询优化 | 避免复杂关联关系处理 | ||
Logstash | 性能调优 | JVM调优 | 扩展JVM堆内存,设置Xms和Xmx为相同值 |
增加工作线程数 | 增加filter和output工作线程数 | ||
配置pipeline.batch.size | 平衡性能和内存开销 |
Elasticsearch调优 Elasticsearch性能优化主要分为两个方面:索引层面和服务器层面。 在索引层面,Elasticsearch性能优化如下。
在服务器层面,Elasticsearch性能优化如下。
Logstash调优 在进行Logstash性能调优时,建议每次仅修改一个配置项并观察性能和资源消耗。通常我们需要考虑的性能指标有CPU、内存和I/O。I/O包括磁盘I/O和网络I/O。Logstash具体的性能调优包括以下几项。
表10-2 自定义日志方式对比
根据配置实体数、接口延迟时间、接口吞吐量等指标对系统资源进行了划分,并给出了使用场景。
表11-1 系统资源参考
表11-2 资源选型
优化
特性 | 描述 | 影响因素 | 注意事项 |
---|---|---|---|
内存缓存配置 | 建议将 mem_cache_size 配置尽可能大,预留足够资源给操作系统和其他程序 | CPU核心数量和服务器内存大小影响内存分配 | 需要根据服务器的实际情况和运行的其他程序进行调整 |
性能指标 | Kong网关性能考量包括延时和吞吐量 | 路由和插件数量增加可能会增加延时 | 延时和吞吐量通常呈反比关系 |
插件基数 | 集群上启用的不同类型插件数量 | 每增加一个插件类型,会消耗更多CPU资源 | 影响请求处理速度 |
大请求/响应处理 | 处理大请求/响应时,Kong网关需缓存到磁盘 | 缓存请求/响应体大小 | 可能导致延时增加 |
表11-3 监控软件对比
网关层具有重要且独特的保护作用,目的是防止外部网络环境中的不安全因素蔓延到内部应用或企业网。对于Kong网关来说,其涉及安全的考量项主要有两个:一个是对后端应用的保护,另一个是对其本身Admin API的保护。 对于后端应用的保护策略,读者可以根据实际场景自主集成Kong网关提供的插件,也可以自定义插件。 这里我们着重讨论Kong网关的Admin API的保护策略。Admin API对外提供了RESTful接口,以便管理和配置服务、路由、插件、使用者以及凭据信息。其具有对Kong服务的完全控制权,因此可确保RESTful接口安全可靠,避免不必要的访问。下面我们提供4种方式对Admin API设置访问控制,包括对网络层、Kong API回路(Loopback)、自定义Nginx配置的访问控制。
安全领域 | 描述 | 实现方法 |
---|---|---|
后端应用保护 | 保护内部应用或企业网免受外部网络环境中的不安全因素影响 | 使用或自定义Kong网关提供的插件进行集成保护 |
Admin API保护 | 保护对Kong服务具有完全控制权的RESTful接口,管理服务、路由等 | 设置访问控制,包括网络层、Kong API回路、自定义Nginx配置等方法 |
微服务12要素是由PaaS先驱Heroku公司CTO——Admin Wiggins提出的。他为微服务开发者提供了一组明确的指引。开发者遵循这些原则,就可以很容易地运行、扩展和部署微服务应用。微服务12要素具体包括如下内容。
要素编号 | 要素名称 | 描述 |
---|---|---|
1 | 基准代码 | 一份基准代码,多份部署 |
2 | 依赖 | 显式声明依赖关系 |
3 | 配置 | 在环境中存储配置 |
4 | 后端服务 | 将后端服务当作附加资源 |
5 | 构建、发布、运行 | 严格分离构建、发布、运行步骤 |
6 | 进程 | 以一个或多个无状态进程运行应用 |
7 | 端口绑定 | 通过端口绑定提供服务 |
8 | 并发 | 通过进程模型进行扩展 |
9 | 可弃性 | 快速启动和优雅终止可最大化健壮性 |
10 | 开发环境与线上环境等价 | 尽可能保持开发、测试、预发布、线上等多套环境一致 |
11 | 日志 | 将日志看作事件流来管理 |
12 | 管理进程 | 将后台管理任务当作一次性进程运行 |
3.过渡策略
策略 | 方法 | 优点 | 缺点 |
---|---|---|---|
冰激凌策略 | 将单体应用的组件分解到单独的服务,逐步过渡到微服务 | 低风险逐步迁移,不影响正常运行和用户体验 | 需要长周期,是渐进过程 |
乐高策略 | 保持老应用原样,新功能作为微服务构建 | 不需对原应用过多改造,快速构建新微服务 | 原应用问题仍存在,需新API支持微服务 |
核按钮策略 | 全部重写单体应用为微服务 | 从头开始重构,整体考量架构方案 | 高人力成本,从头开始,维护两应用 |
图13-3 测试方案全景
图13-4 DevOps平台全局交互