从零手写实现 nginx-23-nginx 对于 cookie 的操作

前言

大家好,我是老马。很高兴遇到你。

我们为 java 开发者实现了 java 版本的 nginx

https://github.com/houbb/nginx4j

如果你想知道 servlet 如何处理的,可以参考我的另一个项目:

手写从零实现简易版 tomcat minicat

手写 nginx 系列

如果你对 nginx 原理感兴趣,可以阅读:

从零手写实现 nginx-01-为什么不能有 java 版本的 nginx?

从零手写实现 nginx-02-nginx 的核心能力

从零手写实现 nginx-03-nginx 基于 Netty 实现

从零手写实现 nginx-04-基于 netty http 出入参优化处理

从零手写实现 nginx-05-MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)

从零手写实现 nginx-06-文件夹自动索引

从零手写实现 nginx-07-大文件下载

从零手写实现 nginx-08-范围查询

从零手写实现 nginx-09-文件压缩

从零手写实现 nginx-10-sendfile 零拷贝

从零手写实现 nginx-11-file+range 合并

从零手写实现 nginx-12-keep-alive 连接复用

从零手写实现 nginx-13-nginx.conf 配置文件介绍

从零手写实现 nginx-14-nginx.conf 和 hocon 格式有关系吗?

从零手写实现 nginx-15-nginx.conf 如何通过 java 解析处理?

从零手写实现 nginx-16-nginx 支持配置多个 server

从零手写实现 nginx-17-nginx 默认配置优化

从零手写实现 nginx-18-nginx 请求头+响应头操作

从零手写实现 nginx-19-nginx cors

从零手写实现 nginx-20-nginx 占位符 placeholder

从零手写实现 nginx-21-nginx modules 模块信息概览

从零手写实现 nginx-22-nginx modules 分模块加载优化

从零手写实现 nginx-23-nginx cookie 的操作处理

前言

大家好,我是老马。

这一节我们将配置的加载,拆分为不同的模块加载处理,便于后续拓展。

在 Nginx 配置文件中,proxy_set_header 指令用于设置在代理请求中传递的 HTTP 头部字段。

通过 proxy_set_header 可以在将请求转发给上游服务器时添加、修改或删除请求头部字段。

具体来说,proxy_set_header Cookie "admin_cookie=admin_value; $http_cookie"; 这条指令用于修改请求头中的 Cookie 字段。

它将一个新的 cookie(admin_cookie=admin_value)添加到现有的请求 cookie 中。详细解释如下:

  1. proxy_set_header 指令:这是 Nginx 用来设置请求头部字段的指令。
  2. Cookie:这是要设置的头部字段名称。在这种情况下,设置的是 HTTP 请求的 Cookie 头部。
  3. "admin_cookie=admin_value; $http_cookie":这是要设置的头部字段值。
    • admin_cookie=admin_value:这是要添加的新 cookie 值。admin_cookie 是 cookie 的名称,admin_value 是它的值。
    • ;:分号用来分隔多个 cookie。
    • $http_cookie:这是一个 Nginx 的内置变量,它包含了当前请求中的所有 cookie 值。

通过这条指令,Nginx 会在转发请求到上游服务器之前,将一个新的 cookie 添加到现有的 cookie 中。这样上游服务器就会收到一个包含新添加的 admin_cookie=admin_valueCookie 头部。

示例配置片段如下:

server {listen 80;server_name example.com;location / {proxy_pass http://backend_server;proxy_set_header Cookie "admin_cookie=admin_value; $http_cookie";}
}

在这个示例中,当客户端向 example.com 发起请求时,Nginx 会将请求转发给 backend_server,并在请求头部的 Cookie 字段中添加一个新的 admin_cookie=admin_value

其他相关的 Nginx 指令

  • proxy_pass:用于定义请求转发到的上游服务器。
  • proxy_set_header:用于设置转发请求的头部字段。

注意事项

  1. 安全性:在操作 cookie 时需要注意安全性,尤其是涉及敏感信息的 cookie。
  2. 兼容性:确保上游服务器能够正确处理添加的 cookie。
  3. 配置顺序proxy_set_header 通常放在 locationserver 块中,并在 proxy_pass 指令之前。

通过合理配置 proxy_set_header 指令,可以在 Nginx 中灵活地操作 HTTP 请求头部,满足各种代理需求。

这个我们原来就支持了

    /*** # 增加或修改请求头* proxy_set_header X-Real-IP $remote_addr;* # 删除请求头* proxy_set_header X-Unwanted-Header "";** @param configParam 参数* @param context     上下文*/@Overridepublic void doBeforeDispatch(NginxCommonConfigParam configParam, NginxRequestDispatchContext context) {List<String> values = configParam.getValues();// $ 占位符号后续处理String headerName = values.get(0);String headerValue = values.get(1);FullHttpRequest fullHttpRequest = context.getRequest();// 设置HttpHeaders headers = fullHttpRequest.headers();if (StringUtil.isEmpty(headerValue)) {headers.remove(headerName);logger.info(">>>>>>>>>>>> doBeforeDispatch headers.remove({})", headerName);} else {// 是否包含if (headers.contains(headerName)) {headers.set(headerName, headerValue);logger.info(">>>>>>>>>>>> doBeforeDispatch headers.set({}, {});", headerName, headerValue);} else {headers.add(headerName, headerValue);logger.info(">>>>>>>>>>>> doBeforeDispatch headers.set({}, {});", headerName, headerValue);}}}

解释

proxy_cookie_domain 是 Nginx 的一个指令,用于修改代理服务器响应中的 Set-Cookie 头部的 Domain 属性。

这个指令通常用于在反向代理配置中,当上游服务器设置的 Domain 属性与客户端访问的域名不一致时,通过重写 Domain 属性来解决跨域问题。

语法

proxy_cookie_domain [上游服务器的域名] [要重写为的域名];
  • 上游服务器的域名:指定要匹配并重写的 Domain 属性值。
  • 要重写为的域名:指定新的 Domain 属性值。

默认值

proxy_cookie_domain off;

如果不设置 proxy_cookie_domain,则默认不对 Set-Cookie 头部的 Domain 属性进行任何修改。

配置范围

该指令可以在 httpserverlocation 块中配置。

示例

假设我们有一个后端服务器 backend.example.com,它在设置 Cookie 时将 Domain 属性设为 backend.example.com

但是,客户端访问的是 www.example.com

我们可以使用 proxy_cookie_domain 来重写 Domain 属性,以便客户端能够正确地接收和发送这些 Cookie。

http {server {listen 80;server_name www.example.com;location / {proxy_pass http://backend.example.com;proxy_cookie_domain backend.example.com www.example.com;}}
}

在这个配置中,当上游服务器 backend.example.com 在响应中返回 Set-Cookie 头部时:

Set-Cookie: sessionid=abcd1234; Domain=backend.example.com; Path=/

Nginx 会将其重写为:

Set-Cookie: sessionid=abcd1234; Domain=www.example.com; Path=/

使用场景

  1. 跨域 Cookie 共享:当后端服务器和客户端使用不同的域名时,通过 proxy_cookie_domain 重写 Set-Cookie 头部的 Domain 属性,使 Cookie 能够在客户端域名下有效。
  2. 域名变更:如果网站的域名发生变化,通过该指令可以确保旧域名设置的 Cookie 仍然有效。
  3. 子域名问题:在使用子域名时,可以通过该指令将所有子域名的 Cookie 统一到主域名下。

注意事项

  1. 安全性:确保重写的域名是可信任的,以防止 Cookie 被不当共享。
  2. 精确匹配proxy_cookie_domain 的匹配是精确匹配的,因此需要确保指定的上游服务器域名与实际的 Set-Cookie 头部中的 Domain 属性完全一致。

通过合理使用 proxy_cookie_domain 指令,可以有效地解决跨域 Cookie 共享的问题,确保在反向代理场景下的 Cookie 设置和使用正确无误。

核心实现如下:

/*** 参数处理类 响应头处理** @since 0.20.0* @author 老马啸西风*/
public class NginxParamHandleProxyCookieDomain extends AbstractNginxParamLifecycleWrite {private static final Log logger = LogFactory.getLog(NginxParamHandleProxyCookieDomain.class);@Overridepublic void doBeforeWrite(NginxCommonConfigParam configParam, ChannelHandlerContext ctx, Object object, NginxRequestDispatchContext context) {if(!(object instanceof HttpResponse)) {return;}List<String> values = configParam.getValues();if(CollectionUtil.isEmpty(values) || values.size() < 2) {return;}// 原始String upstreamDomain = values.get(0);// 目标String targetDomain = values.get(1);HttpResponse response = (HttpResponse) object;HttpHeaders headers = response.headers();String setCookieHeader = headers.get(HttpHeaderNames.SET_COOKIE);if (setCookieHeader != null) {Set<Cookie> cookies = ServerCookieDecoder.STRICT.decode(setCookieHeader);Set<Cookie> modifiedCookies = cookies.stream().map(cookie -> {if (upstreamDomain.equals(cookie.domain())) {Cookie newCookie = new DefaultCookie(cookie.name(), cookie.value());newCookie.setDomain(targetDomain);newCookie.setPath(cookie.path());newCookie.setMaxAge(cookie.maxAge());newCookie.setSecure(cookie.isSecure());newCookie.setHttpOnly(cookie.isHttpOnly());return newCookie;}return cookie;}).collect(Collectors.toSet());List<String> encodedCookies = ServerCookieEncoder.STRICT.encode(modifiedCookies);headers.set(HttpHeaderNames.SET_COOKIE, encodedCookies);}logger.info(">>>>>>>>>>>> doBeforeWrite proxy_hide_header upstreamDomain={} => targetDomain={}", upstreamDomain, targetDomain);}@Overridepublic void doAfterWrite(NginxCommonConfigParam configParam, ChannelHandlerContext ctx, Object object, NginxRequestDispatchContext context) {}@Overrideprotected String getKey(NginxCommonConfigParam configParam, ChannelHandlerContext ctx, Object object, NginxRequestDispatchContext context) {return "proxy_hide_header";}}

支持哪些?

在 Nginx 中,proxy_cookie_flags 指令用于设置从代理服务器返回给客户端的 Set-Cookie 头中特定 cookie 的属性标志。主要支持的配置选项包括:

  1. HttpOnly:将 HttpOnly 标志添加到 cookie,使得 JavaScript 无法通过 document.cookie 访问该 cookie。

    proxy_cookie_flags <cookie_name> HttpOnly;
  2. Secure:将 Secure 标志添加到 cookie,仅在通过 HTTPS 协议发送时才会发送该 cookie。

    proxy_cookie_flags <cookie_name> Secure;
  3. SameSite:设置 SameSite 标志,限制浏览器仅在同站点请求时发送该 cookie,有助于防止跨站点请求伪造(CSRF)攻击。

    proxy_cookie_flags <cookie_name> SameSite=Strict;

    支持的 SameSite 值包括 StrictLaxNone

  4. Max-Age:设置 Max-Age 属性,指定 cookie 的过期时间(秒)。通常用于设置持久化 cookie 的过期时间。

    proxy_cookie_flags <cookie_name> Max-Age=3600;
  5. Expires:设置 Expires 属性,指定 cookie 的过期时间点。通常以 GMT 格式的日期字符串指定。

    proxy_cookie_flags <cookie_name> Expires=Wed, 21 Oct 2026 07:28:00 GMT;
  6. Domain:设置 Domain 属性,指定可接受该 cookie 的域名范围。通过 proxy_cookie_domain 指令更常用地配置。

    proxy_cookie_flags <cookie_name> Domain=example.com;
  7. Path:设置 Path 属性,指定该 cookie 的路径范围。

    proxy_cookie_flags <cookie_name> Path=/;

示例

以下是一些示例,展示如何使用 proxy_cookie_flags 指令设置不同的 cookie 标志:

server {listen 80;server_name example.com;location / {# 添加 HttpOnly 和 Secure 标志proxy_cookie_flags session_cookie HttpOnly Secure;# 设置 SameSite 标志为 Strictproxy_cookie_flags mycookie SameSite=Strict;# 设置 Max-Age 为 1 小时proxy_cookie_flags persistent_cookie Max-Age=3600;# 设置 Expires 属性proxy_cookie_flags old_cookie Expires=Wed, 21 Oct 2026 07:28:00 GMT;# 设置 Domain 属性proxy_cookie_flags global_cookie Domain=example.com;# 设置 Path 属性proxy_cookie_flags local_cookie Path=/subpath;proxy_pass http://backend;}
}

通过这些配置,您可以灵活地控制从代理服务器返回的 Set-Cookie 头中各个 cookie 的属性,以满足安全需求和业务逻辑。

java 核心实现

    public void doBeforeWrite(NginxCommonConfigParam configParam, ChannelHandlerContext ctx, Object object, NginxRequestDispatchContext context) {if(!(object instanceof HttpResponse)) {return;}List<String> values = configParam.getValues();if(CollectionUtil.isEmpty(values) || values.size() < 2) {return;}HttpResponse response = (HttpResponse) object;HttpHeaders headers = response.headers();String cookieHeader = headers.get(HttpHeaderNames.COOKIE);final String cookieName = values.get(0);if (cookieHeader != null) {Set<Cookie> cookies = ServerCookieDecoder.STRICT.decode(cookieHeader);Set<Cookie> modifiedCookies = cookies.stream().map(cookie -> {// 相同的名字if (cookieName.equals(cookie.name())) {// HttpOnly Securefor(int i = 1; i < values.size(); i++) {String value = values.get(i);if("HttpOnly".equals(value)) {cookie.setHttpOnly(true);}if("Secure".equals(value)) {cookie.setSecure(true);}// 拆分if(!value.contains("=")) {return cookie;}String[] items = value.split("=");String itemKey = items[0];String itemVal = items[1];//                        if("SameSite".equals(itemKey) && "Strict".equals(itemVal)) {
//                        }if("Max-Age".equals(itemKey)) {cookie.setMaxAge(Long.parseLong(itemVal));}if("Expires".equals(itemKey)) {Date expireDate = calcDate(itemVal);long maxAge = expireDate.getTime() - System.currentTimeMillis();cookie.setMaxAge(maxAge);}if("Domain".equals(itemKey)) {cookie.setDomain(itemVal);}if("Path".equals(itemKey)) {cookie.setPath(itemVal);}}}return cookie;}).collect(Collectors.toSet());List<String> encodedCookies = ServerCookieEncoder.STRICT.encode(modifiedCookies);headers.set(HttpHeaderNames.COOKIE, encodedCookies);}logger.info(">>>>>>>>>>>> doBeforeWrite proxy_cookie_flags values={}", values);}

介绍

在 Nginx 中,proxy_cookie_path 指令用于修改传递到后端服务器的 HTTP 请求中的 Cookie 的路径。

这个指令通常在反向代理服务器配置中使用,用于调整传递给后端服务器的 Cookie 的路径信息,以适应后端服务器的预期路径结构。

语法和用法

语法:

proxy_cookie_path regex path;

参数解释:

  • regex:一个正则表达式,用于匹配要修改的 Cookie 的路径。
  • path:要替换成的路径。

示例

假设有如下配置:

location /app/ {proxy_pass http://backend.example.com;proxy_cookie_path ~*^/app(.*) $1;
}

在这个示例中:

  • proxy_cookie_path 指令配合 proxy_pass 使用,表示将从客户端接收的带有路径 /app/ 的 Cookie 的路径信息去除 /app 部分后再传递给后端服务器。

例如,如果客户端发送的 Cookie 路径是 /app/session, Nginx 将修改为 /session 后传递给后端服务器。

注意事项

  • 使用 proxy_cookie_path 时,确保理解你的后端服务器期望接收的 Cookie 路径格式,以便正确设置正则表达式和路径。
  • 正则表达式必须能够正确匹配客户端发送的 Cookie 路径。
  • 这个指令通常用于调整不同路径的代理请求,以便与后端服务器的预期路径结构匹配。

java 核心实现

public void doBeforeDispatch(NginxCommonConfigParam configParam, NginxRequestDispatchContext context) {List<String> values = configParam.getValues();if(CollectionUtil.isEmpty(values) || values.size() < 2) {throw new Nginx4jException("proxy_cookie_path 必须包含2个参数");}FullHttpRequest request = context.getRequest();// 原始String regex = values.get(0);String path = values.get(1);HttpHeaders headers = request.headers();String cookieHeader = headers.get(HttpHeaderNames.COOKIE);if (cookieHeader != null) {String modifiedCookieHeader = cookieHeader.replaceAll(regex, path);headers.set(HttpHeaderNames.COOKIE, modifiedCookieHeader);}logger.info(">>>>>>>>>>>> doBeforeDispatch proxy_cookie_path replace regex={} => path={}", regex, path);
}

小结

对于 cookie 的处理,让我们的请求可以更加强大灵活。

  1. proxy_cookie_domain: 设置后端服务器响应的 Cookie 中的域名。

  2. proxy_cookie_flags: 设置后端服务器响应的 Cookie 的标志位。

  3. proxy_cookie_path: 设置后端服务器响应的 Cookie 的路径。

我是老马,期待与你的下次重逢。

开源地址

为了便于大家学习,已经将 nginx 开源

https://github.com/houbb/nginx4j

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/27479.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信号与系统实验MATLAB-实验2-连续时间系统的时域分析

实验二 连续时间系统的时域分析 一、实验目的 1、掌握连续时间信号卷积及其MATLAB实现方法&#xff1b; 2、掌握连续系统的冲激响应、阶跃响应及其MATLAB实现方法&#xff1b; 3、掌握利用MATLAB求LTI系统响应的方法&#xff1b; 4、掌握利用MATLAB求函数卷积和解微分方程…

网络IO模型:BIO NIO AIO 的区别!!!

BIO是同步阻塞I/O模型&#xff0c;它使用一个线程来处理一个请求&#xff0c;如果这个请求没有被处理完&#xff0c;这个线程就会一直等待&#xff0c;直到请求处理完成。这种模型适用于连接数较小的情况。 NIO是同步非阻塞I/O模型&#xff0c;它使用单个线程来处理多个请求&a…

APM之:卡顿监控

方案一&#xff1a;参考了ANR-WatchDog机制 ANR-WatchDog机制原理不复杂&#xff0c;它内部启动了一个子线程&#xff0c;定时通过主线程Handler发送Message&#xff0c;然后定时去检查Message的处理结果。 通俗来说就是利用了Android系统MessageQueue队列的排队处理特性。 …

学习grdecl文件格式之后的事情

学习了grdecl文件格式&#xff0c;搞地质的专业人士都知道&#xff0c;这是专门用在地质上的油藏软件&#xff08;个人感觉就是斯伦贝谢的Petrel的&#xff09;的一种文件格式&#xff0c;正好自己也在学习三维的开发&#xff0c;顺手写了一个简单的读取grdecl算法&#xff0c;…

Vue3【十九】自定义Hooks钩子 将数据和方法分组

Vue3【十九】自定义Hooks钩子 将数据和方法分组 Vue3【十九】自定义Hooks钩子 将数据和方法分组 每个分组都可以放置 各种生命周期钩子 分组和可以使用计算属性等 案例截图 目录结构 代码 person.vue <template><div class"person"><h2>Vue3自定…

Linux指令学习(4)

目录 0.普通用户和root用户之间的切换 1.head/tail指令 2.管道 3.date命令 4.三个查找相关的指令 5.文件过滤grep 6.打包和压缩 5.zip/unzip指令 0.普通用户和root用户之间的切换 &#xff08;1&#xff09;这个我们之前不是经常使用这个root用户吗&#xff0c;现在随着…

NLP--逻辑回归

1.定义 如何解决二元分类问题&#xff0c;除了上节我们谈到的贝叶斯分类器&#xff0c;我们可以通过计算数据属于不同类别的概率进行分类的逻辑回归。虽然有回归二字&#xff0c;但逻辑回归解决的是分类问题&#xff0c;也可以用于两类以上的多分类问题。 2.方法 概率是介于0到…

python操作jenkins

参考链接&#xff1a; python操作jenkins

数据结构笔记39-48

碎碎念&#xff1a;想了很久&#xff0c;不知道数据结构这个科目最终该以什么笔记方式呈现出来&#xff0c;是纸质版还是电子版&#xff1f;后来想了又想&#xff0c;还是电子版吧&#xff1f;毕竟和计算机有关~&#xff08;啊哈哈哈哈哈哈哈&#xff09; 概率论已经更新完了&…

代码随想录训练营第八天 151反转字符串中的单词 右旋字符串

第一题&#xff1a; 原题链接&#xff1a;151. 反转字符串中的单词 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 先把首尾的空格去掉&#xff1a;找到第一个不是空格的字符&#xff0c;找到最后一个不是空格的字符。substr字符串为新的字符串t。 使用双指针&…

【Python入门与进阶】Jupyter Notebook配置与优化

目录 1.Jupyter Notebook简介 2.Jupyter Notebook的安装 2.1 命令行安装 2.2 可视化界面安装 3.Jupyter Notebook的使用 3.1 启动 Jupyter Notebook 3.2 Jupyter Notebook 界面介绍 3.3 创建新的 Notebook 3.4 编写和运行代码单元 3.5 使用 Markdown 编写文档 3.6 保…

快慢指针在字符串中的应用-443. 压缩字符串

题目链接及描述 443. 压缩字符串 - 力扣&#xff08;LeetCode&#xff09; 题目分析 这个题目总体不算太难&#xff0c;如果之前接触过双指针&#xff08;快慢指针&#xff09;的话&#xff0c;比较好做。题目可以理解为计算数组中对应各个连续字符出现的次数&#xff0c;并将…

SAPUI5基础知识5 - 控件(control)的使用

1. 背景 在SAPUI5中&#xff0c;控件&#xff08;Control&#xff09;是构建用户界面的基本元素。控件是一个可重用的组件&#xff0c;它可以与用户进行交互或显示信息。 每个控件都有自己的特性&#xff0c;例如属性&#xff08;Properties&#xff09;、聚合&#xff08;Agg…

btrace:binder_transaction+eBPF+Golang实现通用的Android APP动态行为追踪工具

一、简介&#xff1a; 在进行Android恶意APP检测时&#xff0c;需要进行自动化的行为分析&#xff0c;一般至少包括行为采集和行为分析两个模块。其中&#xff0c;行为分析有基于规则、基于机器学习、基于深度学习甚至基于大模型的方案&#xff0c;各有各的优缺点&#xff0c;不…

CentOS 7基础操作14_Linux组账号管理

在5.1.2节学习了管理Linux操作系统中用户账号的相关命令&#xff0c;接下来继续学习组账号管理的相关命令。组账号管理命令的使用相对较少&#xff0c;主要包括groupadd、groupdel、gpasswd等。 对于用户账号来说&#xff0e;对应的组账号可分为基本组和附加组两种类型&#xf…

【AI开发】LangGraph基础

在LangGraph中有三个重要元素 StateGraphNodeEdge StateGraph 首先stategraph是用来描述整个图的&#xff0c;图中的状态会随着多个agent的工作不断的更新&#xff0c;节点node就是用来更新状态的 如何来定义一张图中的状态 每个应用的状态可能不同&#xff0c;所以我们需要…

kettle实时增量同步mysql数据

** 本文主要介绍运用kettle实时增量同步mysql数据 ** Debezium介绍 官网地址&#xff1a;https://debezium.io/documentation/ Debezium是一个开源项目&#xff0c;为捕获数据更改(Capture Data Change,CDC)提供了一个低延迟的流式处理平台&#xff0c;通过安装配置Debeziu…

Aigtek高压功率放大器在超声电机中的应用

超声电机是一种先进的电机技术&#xff0c;常用于各种应用&#xff0c;如医疗成像、工业自动化和汽车技术。这些电机在高速、高精度和低噪音要求的领域中表现出色。在驱动这些超声电机时&#xff0c;高压功率放大器发挥着关键作用。本文将介绍高压功率放大器如何驱动超声电机&a…

腾讯元宝APP:AIGC大模型的新篇章

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已经渗透到我们生活的方方面面。腾讯作为国内科技巨头&#xff0c;近期推出的元宝APP更是为AIGC&#xff08;人工智能生成内容&#xff09;市场注入了新的活力。这款大模型产品的上线&#xff0c;不仅丰富…

【kyuubi-spark】从0-1部署kyuubi集成spark执行spark sql到k8s读取iceberg的minio数据

一、背景 团队在升级大数据架构 前端使用trino查询&#xff0c;对trino也进行了很多优化&#xff0c;目前测试来看&#xff0c;运行还算稳定&#xff0c;但是不可避免的trino的任务总会出现失败的情况。原来的架构是trino失败后去跑hive&#xff0c;而hive是跑mapreduce依赖于…