Azure设计模式之网关模式
使用网关将多个请求聚合到单一请求中。当客户端对不同的后端系统进行多次调用时, 此模式非常有用。
问题背景
有时客户端可能需要对不同后端服务进行多次调用。依赖多服务来执行任务的应用程序导致每个请求上耗费额外资源。当向应用程序添加任何新功能或服务时,导致额外的请求,进而增加资源和网络的使用。客户端和后端之间过多的信息通信对应用程序的性能和扩展产生了负面影响。在微服务架构中这个问题显得更加普遍,由多个小服务构建的应用程序自然会有更多的跨服务调用。
在下图中,客户端向服务发送请求(1、2、3)。每个服务处理请求并响应应用程序(4、5、6)。在通常具有高延迟的蜂窝网络中,这种方式的效率很低,可能导致连接中断或请求信息不完整。虽然请求可以并行完成,但应用程序必须经历发送、等待和处理每个请求的数据,这些步骤都必须在单独的连接上,从而增加了失败的几率。
解决方案
使用聚合网关来减少客户端和服务之间的信息交互。网关接收客户端请求,将请求分发到不同后端系统,然后将聚合结果发送回请求的客户端。
此模式可以减少应用程序对后端服务的请求数, 并通过高延迟的代价提高应用程序性能。
在下图中,应用程序向网关(1)发送一个请求。该请求包含一个附加请求的包。网关将每个请求分发给相关服务(2)。每个服务返回对网关的响应(3)。网关将每个服务的响应结果进行聚合,并发送到应用程序(4)。应用程序只需要和网关通信。
问题和注意事项
网关不应为后端服务引入耦合。
网关应部署在后端服务附近,从而减少延迟。
网关服务可能会成为单点故障。确保网关的设计得当满足应用程序的可用性要求。
网关可能会成为瓶颈。确保网关足够提供的性能来处理负载,并能够满足应用的可扩展要求。
对网关执行负载测试, 以确保不会给服务带来级联失败。
使用诸如舱壁、断路、重试和超时等技术实现弹性设计。
如果一个或多个服务调用耗时太长, 则超时并返回部分数据集或许是可以接受的。需要对这些情况进行处理。
使用异步i/o以确保后端的延迟不会导致应用程序出现性能问题。
使用相关id实现分布式跟踪或跟踪每个单独的调用情况。
监视请求和响应大小。
考虑在故障转移策略中借助缓存。
将聚合服务放在网关后面,而不是构建到网关内。请求聚合可能对其他相关服务资源有依赖,以至于会影响网关的路由和卸载功能。
何时使用此模式
在以下情况下使用此模式:
客户端需要与多个后端服务进行通信以执行操作。
客户端高延迟的网络, 如蜂窝网络。
此模式在以下情况下可能不合适:
希望在多个操作之间减少客户端与某服务的调用次数。在这种情况下,最好将批处理操作添加到服务中。客户端或应用程序部署在后端服务附近。
例子
下面的示例是Lua创建一个简单的网关聚合NGINX服务。
相关阅读
为前端创建后端(https://docs.microsoft.com/en-us/azure/architecture/patterns/backends-for-frontends)
网关卸载模式(https://docs.microsoft.com/en-us/azure/architecture/patterns/gateway-offloading)
网关路由模式(https://docs.microsoft.com/en-us/azure/architecture/patterns/gateway-routing)
问题背景
有时客户端可能需要对不同后端服务进行多次调用。依赖多服务来执行任务的应用程序导致每个请求上耗费额外资源。当向应用程序添加任何新功能或服务时,导致额外的请求,进而增加资源和网络的使用。客户端和后端之间过多的信息通信对应用程序的性能和扩展产生了负面影响。在微服务架构中这个问题显得更加普遍,由多个小服务构建的应用程序自然会有更多的跨服务调用。
在下图中,客户端向服务发送请求(1、2、3)。每个服务处理请求并响应应用程序(4、5、6)。在通常具有高延迟的蜂窝网络中,这种方式的效率很低,可能导致连接中断或请求信息不完整。虽然请求可以并行完成,但应用程序必须经历发送、等待和处理每个请求的数据,这些步骤都必须在单独的连接上,从而增加了失败的几率。
解决方案
使用聚合网关来减少客户端和服务之间的信息交互。网关接收客户端请求,将请求分发到不同后端系统,然后将聚合结果发送回请求的客户端。
此模式可以减少应用程序对后端服务的请求数, 并通过高延迟的代价提高应用程序性能。
在下图中,应用程序向网关(1)发送一个请求。该请求包含一个附加请求的包。网关将每个请求分发给相关服务(2)。每个服务返回对网关的响应(3)。网关将每个服务的响应结果进行聚合,并发送到应用程序(4)。应用程序只需要和网关通信。
问题和注意事项
网关不应为后端服务引入耦合。
网关应部署在后端服务附近,从而减少延迟。
网关服务可能会成为单点故障。确保网关的设计得当满足应用程序的可用性要求。
网关可能会成为瓶颈。确保网关足够提供的性能来处理负载,并能够满足应用的可扩展要求。
对网关执行负载测试, 以确保不会给服务带来级联失败。
使用诸如舱壁、断路、重试和超时等技术实现弹性设计。
如果一个或多个服务调用耗时太长, 则超时并返回部分数据集或许是可以接受的。需要对这些情况进行处理。
使用异步i/o以确保后端的延迟不会导致应用程序出现性能问题。
使用相关id实现分布式跟踪或跟踪每个单独的调用情况。
监视请求和响应大小。
考虑在故障转移策略中借助缓存。
将聚合服务放在网关后面,而不是构建到网关内。请求聚合可能对其他相关服务资源有依赖,以至于会影响网关的路由和卸载功能。
何时使用此模式
在以下情况下使用此模式:
客户端需要与多个后端服务进行通信以执行操作。
客户端高延迟的网络, 如蜂窝网络。
此模式在以下情况下可能不合适:
希望在多个操作之间减少客户端与某服务的调用次数。在这种情况下,最好将批处理操作添加到服务中。客户端或应用程序部署在后端服务附近。
例子
下面的示例是Lua创建一个简单的网关聚合NGINX服务。
worker_processes 4;
events {
worker_connections 1024;
}
http {
server {
listen 80;
location = /batch {
content_by_lua '
ngx.req.read_body()
-- read json body content
local cjson = require "cjson"
local batch = cjson.decode(ngx.req.get_body_data())["batch"]
-- create capture_multi table
local requests = {}
for i, item in ipairs(batch) do
table.insert(requests, {item.relative_url, { method = ngx.HTTP_GET}})
end
-- execute batch requests in parallel
local results = {}
local resps = { ngx.location.capture_multi(requests) }
for i, res in ipairs(resps) do
table.insert(results, {status = res.status, body = cjson.decode(res.body), header = res.header})
end
ngx.say(cjson.encode({results = results}))
';
}
location = /service1 {
default_type application/json;
echo '{"attr1":"val1"}';
}
location = /service2 {
default_type application/json;
echo '{"attr2":"val2"}';
}
}
}
相关阅读
为前端创建后端(https://docs.microsoft.com/en-us/azure/architecture/patterns/backends-for-frontends)
网关卸载模式(https://docs.microsoft.com/en-us/azure/architecture/patterns/gateway-offloading)
网关路由模式(https://docs.microsoft.com/en-us/azure/architecture/patterns/gateway-routing)