依赖Jetty实现流转发功能的实践

本文介绍了从nginx-lua迁移到Java实现文件下载服务的原因,并详细阐述了如何依赖Jetty实现流转发功能,包括开启Servlet的异步支持、确定异步写入API的选择,以及最终选择Jetty内置的HttpClient完成任务。过程中分析了ByteBuffer、InputStream和ReadableByteChannel的限制,最终找到了适合的解决方案。
摘要由CSDN通过智能技术生成

最近在写文件的下载服务,主要功能是将请求URL调用业务接口进行解析,解析到真实的下载地址,然后将下载流透传出去。这一部分之前使用nginx-lua实现,由于维护过于困难(优雅上下线、截流、熔断能力缺乏, 证书相关运维支持缺失),因此改用Java实现。本文也主要论述如何依赖Jetty实现流转发功能。由于对Jetty的依赖非常深,建议使用EmbeddedJettyServer以引入和统一Jetty依赖。

为什么要阅读Jetty高层IO代码

  1. 下载服务必须采用AIO,以避免客户端或存储端带宽对服务表现的影响。
  2. 对于AIO机制,servlet-api中并没有相关标准。
  3. 自建AIO事件循环或自实现Http协议难度大,而且需要较长时间测试以保证代码健壮性。
  4. Jetty作为被依赖Web容器,本身就具有AIO能力。

开启Servlet的异步支持

首先,需要在HttpServletRequest中开启异步支持,如果不开启异步支持,会造成请求提前被返回引起流中断(servlet-api 3.1.0版本以上支持此功能)。

private void startAsync(HttpServletRequest request) {
    AsyncContext asyncContext = request.startAsync();
    // 异步任务设为不会超时
    asyncContext.setTimeout(0);
} 

确定异步写入Api

之后,我们需要了解Jetty是如何写入Http响应体的,我们能不能调用Jetty的方法异步写入Http响应体。

最直接的想法就是查看一下servlet-api中的javax.servlet.ServletOutputStream的实现类,有没有相关异步写入的方法。

通过代码阅读,很容易就可以找到javax.servlet.ServletOutputStream的实现类,也就是我们的主角org.eclipse.jetty.server.HttpOutput。

它身上有以下AIO相关的方法(仅截取三个关心的方法):

 /**
 * Asynchronous send of whole content.
 *
 * @param content  The whole content to send
 * @param callback The callback to use to notify success or failure
 */
public void sendCon
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值