使用Nginx的代理TCP流(MySQL和Redis)

Ana*_*oly 19 mysql performance load-balancing nginx redis

我读到了Nginx Fabric Model,它引起了我的注意力,重新配置应用程序如何与MySQL和Redis进行通信.如果本地Nginx实例可以高效且快速地代理HTTP流量,那么现在它也可以代理TCP而不必担心网络,即使在紧急情况下使用数据库slave作为主服务器并且可能封装数据库分片.所有这些好处都可以简化应用程序配置及其逻辑,网络(拥塞,延迟,超时,重试)将不再是功能开发的重点.

我使用最新的Docker和一组容器:Nginx,Redis,MySQL.我尝试了以下配置:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log info;
pid        /var/run/nginx.pid;


events {
  worker_connections  1024;
}

stream {
  upstream redis {
    # prefer first server but limit connections
    server 172.17.0.8:6379 weight=2 max_conns=1;
    server 172.17.0.3:6379;
  }

  upstream mysql {
    # use second server in case of failure
    server 172.17.0.4:3306;
    server 172.17.0.5:3306 backup;
  }

  server {
    listen 6379 so_keepalive=on;
    proxy_pass redis;
  }

  server {
    listen 3306 so_keepalive=on;
    proxy_pass mysql;
  }
}
Run Code Online (Sandbox Code Playgroud)

我有一些问题:

  • 日志记录 - 如何知道正在使用哪个端点,Nginx重试特定请求的次数?

  • 实时统计 - 是否可以获得流模块的吞吐量?

  • 从数据库分片角度来看 - 是否可以根据除$ remote_addr之外的某些逻辑将请求分派给分片数据库?

最后一个问题非常重要,我发现模块ngx_stream_map_modulengx_stream_split_clients_module但是$ remote_addr不适合分片,我们可以从http部分拦截cookie并在流部分重用我们没有任何头部吗?我们可以在流部分注入Lua代码吗?是ngx_stream_ssl_preread_module对于这个问题的解决方案,如何让它为不加密的连接工作?

The*_*i.9 1

我不认为 N​​ginx 可以用于您想要使用它的用途。虽然它可用于代理 tcp 流或对其进行负载平衡,但它不一定了解其中的协议和请求结构。所以回答你的问题:

从数据库分片的角度来看 - 是否可以基于 $remote_addr 之外的某些逻辑将请求分派到分片数据库?

并不真地。它无法根据内容将不同的 Redis 请求或 MySQL 查询从单个连接路由到不同的服务器,因为这些东西对于 nginx 来说只是一个它无法读取的流。它在流启动期间为其分配一个目的地,并确保所有来回的数据包都到达相同的目的地,仅此而已。

例如,在您链接的 MySQL 分片文章中,它执行 mysql 命令提示符来运行单个查询并检查节点名称。每次运行时,它都会建立连接,运行查询,然后断开连接。因此,每次执行此操作时,新连接都会由 nginx 路由到另一台服务器。但是,如果您要在同一个 mysql 命令提示符实例上运行相同的查询两次,它会给您相同的节点名称。还值得注意的是,这是使用 MySQL Galera,它是 MySQL 的多主配置,可以在其内部处理读写路由,从而允许像这样的任意客户端查询路由。但对于 redis 来说情况并非如此。

此外,这本质上也不会消除应用程序的所有连接处理。在许多情况下,诸如下游不可用之类的错误仍可能传播到客户端。

您也许可以使用它来简化应用程序的配置,但是,它也可能只是将复杂性推入本地 nginx 配置。所以这可能是也可能不是实际的好处。


我们可以从 http 部分拦截 cookie 并在没有任何标头的流部分中重用吗?

可能不会。HTTP 标头不会传递到数据库连接,因为它们是根本不同的协议,因此即使 nginx 可以读取流,它也无法使用它。


我们可以在流部分注入Lua代码吗?

这可能是可能的,但需要一个能够解析应用程序协议的 Lua 模块,例如 Redis 和 MySQL 的有线协议。但正如我之前提到的,从数据库/一致性的角度来看,在连接内路由请求(即使您可以在 nginx 中检测并路由它们)并不一定简单,我真的不建议这样做。