- 浏览: 1595482 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
jsrgzhangzhiyong:
关于null值的转换还是感觉不太友好,就像 mapstruct ...
我也造了个轮子:BeanMapping(属性拷贝) -
he037:
a417930422 写道引用使用EPHEMERAL会引出一个 ...
基于zookeeper的分布式lock实现 -
seancheer:
qianshangding 写道首先节点启动后,尝试读取本地的 ...
zookeeper学习记录三(session,watcher,persit机制) -
雪夜归人:
您好,我想咨询一下,开源的canal都能支持mysql的哪些版 ...
Canal BinlogChange(mysql5.6) -
zhoudengyun:
copy 一份做记录,后续学习,请知悉
阿里巴巴开源项目: 基于mysql数据库binlog的增量订阅&消费
背景
最近在做的一个项目,两个java进程之间会涉及一个大数据量的传递过程,基本都是图片文件,(做了压缩后还是会比较大,最大的有超过600MB)。其次这两个java进程是在跨机房,比如中国和美国机房,网络待框也就几百kB。
这就是本文的项目背景
分析
1. 600MB的文件,都是A进程运行时根据需要生成的(下载需要的图片文件)。所以无法预先处理,而且公司总图片文件都是以TB计算,所以全量同步的方案也不靠谱
2. 从A进程到B进程的数据传递,首先想到用socket进行传递,但单socket的数据同步无法满足需求,多线程数据传递会涉及数据的切片和数据的合并等,代码相对会比较复杂
老的项目实现:
- A先临时保存文件到一指定目录
- A进程机器上启动一个http服务(比如nginx,lighttpd)
- B进程外部调用一个多线程下载客户端,下载数据到一临时目录
- B进程等下载完成后,再操纵临时目录的数据
过程
涉及到多线程下载和断点续载,首先得了解一个Http协议的内容。
Byte Ranges: 文档http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
大致的内容,可以在Http的Header头中进行添加,可以指定文件下载byte的start和end的位置,几个例子:
bytes=100-499 bytes=-300 bytes=100- bytes=1-2,2-3,6-,-2
最后,通过tcpdump进行数据抓包分析,多线程下载客户端的Http协议的内容。基本的思路是根据线程数,计算出每个线程的bytes-range,然后每个线程发起一个独立的请求。后端每个处理线程单独处理bytes-range的数据下载。
至于断点续传,其实也相对比较简单了。就是记录好分出去的每个bytes-range成功与否,失败的重新再做,已经做完的可以直接跳过。
抓取的Http协议内容:
GET /source.tar.gz HTTP/1.1 User-Agent: aria2/1.13.0 Accept: */* Host: 10.20.156.49:8080 Pragma: no-cache Cache-Control: no-cache Range: bytes=258998272-387973119
java版的多线程下载支持
一提到做java版的多线程下载,首先就会想到jetty和tomcat。tomcat只能以外部server的方式进行启动,和nginx没有太多的区别。
最后我选择了jetty,并在项目中做为嵌入式进行启动,提供http多线程下载服务。
按照前面的分析,要做多线程下载,无非就是要实现一个bytes-range的处理。还好我用的jetty版本(7.0.1)已经解析了bytes-range,具体解析类:InclusiveByteRange
再仔细翻了下它的代码,发现jetty已经默认提供了一个servlet支持多线程下载,就是DefaultServlet,甚喜。
最后,按照我项目的需求适当的裁剪了一些代码,最后完成了:DownloadServlet,具体代码见附件。
类中使用了java版的sendfile,推荐看一下:http://stackoverflow.com/questions/1605332/java-nio-filechannel-versus-fileoutputstream-performance-usefulness
将jetty引入做为嵌入式启动的步骤
1. 引入相关的jar
<dependency> <groupId>com.alibaba.external</groupId> <artifactId>server.jetty.jetty-servlet</artifactId> <version>${jetty_verion}</version> </dependency> <dependency> <groupId>com.alibaba.external</groupId> <artifactId>server.jetty.jetty-xml</artifactId> <version>${jetty_verion}</version> </dependency> <dependency> <groupId>com.alibaba.external</groupId> <artifactId>server.jetty.jetty-server</artifactId> <version>${jetty_verion}</version> </dependency>
2. 配置jetty.xml (我选择了xml的配置方式,但没有使用war包,我只需要一个Http服务功能即可)
<Configure id="Server" class="org.eclipse.jetty.server.Server"> <!-- =========================================================== --> <!-- Server Thread Pool --> <!-- =========================================================== --> <Set name="ThreadPool"> <!-- Default queued blocking threadpool --> <New class="org.eclipse.jetty.util.thread.QueuedThreadPool"> <Set name="minThreads">10</Set> <Set name="maxThreads">250</Set> </New> </Set> <!-- =========================================================== --> <!-- Set connectors --> <!-- =========================================================== --> <!-- --> <Call name="addConnector"> <Arg> <New class="org.eclipse.jetty.server.bio.SocketConnector"> <Set name="port"><Property name="jetty.bio.port" default="8080"/></Set> <Set name="forwarded">true</Set> <Set name="forwardedHostHeader">ignore</Set> <Set name="forwardedServerHeader">ignore</Set> <Set name="acceptQueueSize">256</Set> <Set name="statsOn">false</Set> <Set name="maxIdleTime">600000</Set> <Set name="lowResourcesMaxIdleTime">5000</Set> <Set name="requestHeaderSize">8192</Set> <Set name="responseHeaderSize">8192</Set> </New> </Arg> </Call> <!-- <Call name="addConnector"> <Arg> <New class="org.eclipse.jetty.server.nio.SelectChannelConnector"> <Set name="host"><Property name="jetty.host" /></Set> <Set name="port"><Property name="jetty.port" default="8080"/></Set> <Set name="forwarded">true</Set> <Set name="forwardedHostHeader">ignore</Set> <Set name="forwardedServerHeader">ignore</Set> <Set name="maxIdleTime">600000</Set> <Set name="Acceptors">2</Set> <Set name="acceptQueueSize">256</Set> <Set name="statsOn">false</Set> <Set name="confidentialPort">8443</Set> <Set name="lowResourcesConnections">2000</Set> <Set name="lowResourcesMaxIdleTime">5000</Set> <Set name="requestHeaderSize">8192</Set> <Set name="responseHeaderSize">8192</Set> </New> </Arg> </Call> --> <!-- =========================================================== --> <!-- Set handler Collection Structure --> <!-- =========================================================== --> <Set name="handler"> <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection"> <Set name="handlers"> <Array type="org.eclipse.jetty.server.Handler"> <Item> <New id="ServletHandler" class="org.eclipse.jetty.servlet.ServletContextHandler"> <Set name="contextPath">/</Set> <Call name="addServlet"> <Arg>com.alibaba.otter.task.biz.common.jetty.DownloadServlet</Arg> <Arg>/*</Arg> </Call> <Get name="initParams"> <Put name="org.eclipse.jetty.servlet.Default.resourceBase">/tmp/</Put> <Put name="org.eclipse.jetty.servlet.Default.gzip">false</Put> </Get> </New> </Item> </Array> </Set> </New> </Set> <!-- =========================================================== --> <!-- extra options --> <!-- =========================================================== --> <Set name="stopAtShutdown">true</Set> <Set name="sendServerVersion">false</Set> <Set name="sendDateHeader">true</Set> <Set name="gracefulShutdown">1000</Set> </Configure>
说明: 主要的配置见handler,配置了对应的DownloadServlet
3. 启动入口 (使用了xml配置后就灰常的简洁了)
Resource jetty_xml = Resource.newSystemResource("jetty/jetty.xml"); XmlConfiguration configuration = new XmlConfiguration(jetty_xml.getInputStream()); Server server = (Server) configuration.configure(); server.start();
测试
最后选择了几个多线程下载的客户端进行了测试,我这里选择了aria2c(http://aria2.sourceforge.net/) 和 axel(http://www.axel.com/uk2/)
aria2c测试
参数:
--no-conf -x 10 -s 10 -j 10 --timeout=600 --max-tries=5 --stop=1800 --allow-overwrite=true --enable-http-keep-alive=true --log-level=warn
下载1.1GB的文件:
apache : 28s
nginx : 27s
jetty : 27s
-n 10 -a -v
下载1.1GB的文件:
apache : 87s
nginx : 87s
jetty : 88s
总结
并没有做非常详尽的性能测试,不过从几次跑的结果来看,基本上也有数了。
- jetty实现的servlet性能基本和nginx,apache下载接近。而且测试过程中瓶颈已经不在应用本身,基本都在网络带宽上了,我是百MB网卡,基本可以满负荷运转。
- jetty的nio和bio版本,nio在context switch切换上会相对比较多(因为有大量的READ/WRITE事件响应,线程切换反而不如bio来得少),建议部署bio模式
- 多线程下载aria2c工具的确不错,推荐使用
评论
toogoot#gmail.com谢谢!
https://gist.github.com/4633039
感谢!
toogoot#gmail.com谢谢!
https://gist.github.com/4633039
toogoot#gmail.com谢谢!
端口不同,当然可以
操作系统层面会对文件流有cache,上一次下载后会有cache,会音像测试结果。
发表评论
-
yugong QuickStart
2016-03-05 01:52 0几点说明 a. 数据迁移的方案可参见设计文档,oracl ... -
阿里巴巴开源项目: 阿里巴巴去Oracle数据迁移同步工具
2016-03-05 18:29 6509背景 08年左右,阿里巴巴开始尝试MySQL的相关 ... -
愚公performance
2016-03-02 17:29 0性能测试 全量测试 场景1 (单主键, ... -
yugong AdminGuide
2016-03-02 16:40 0环境要求 操作系统 数据库 迁移方案 部署 ... -
Tddl_hint
2014-01-27 13:52 0背景 工作原理 Hint格式 direct模 ... -
tddl5分库规则
2014-01-26 14:41 0背景 工作原理 构建语法树 元数据 基于 ... -
tddl5优化器
2014-01-22 15:12 0背景 工作原理 构建语法树 元数据 抽象语 ... -
Canal BinlogChange(mariadb5/10)
2014-01-20 17:25 4587背景 先前开源了一个 ... -
asynload quickstart
2013-10-08 22:49 0几点说明: 1. asyncload是做为一个j ... -
映射规则配置
2013-09-26 11:25 0背景 因为alibaba的特殊业务,比如: 同 ... -
网友文档贡献
2013-09-18 15:50 01. Otter源代码解析系列 链接:http://e ... -
Manager配置介绍
2013-09-16 13:00 0通道配置说明 多种同步方式配置 a. 单向同步 ... -
canal&otter FAQ
2013-09-05 17:30 0常见问题 1. canal和 ... -
阿里巴巴开源项目:分布式数据库同步系统otter(解决中美异地机房)
2013-08-22 16:48 40433项目背景 阿里巴巴B2B公司,因为业务的特性 ... -
Otter AdminGuide
2013-08-19 11:06 0几点说明 otter系统自带了manager,所以简化了一 ... -
Otter高可用性
2013-08-17 23:41 0基本需求 网络不可靠,异地机房尤为明显. man ... -
Otter数据一致性
2013-08-17 23:39 0技术选型分析 需要处理一致性的业务场景: 多地修改 ( ... -
Otter扩展性
2013-08-17 22:20 0扩展性定义 按照实现不同,可分为两类: 数据处理自定 ... -
Otter双向回环控制
2013-08-17 21:37 0基本需求 支持mysql/oracle的异构数据库的双 ... -
Otter调度模型
2013-08-17 20:13 0背景 在介绍调度模型之前,首先了解一下otter系统要解 ...
相关推荐
通过使用NIO(非阻塞I/O)API,Jetty可以高效地管理多个连接,而不会因为等待I/O操作完成而消耗大量的线程资源。 在实际应用中,我们可以通过以下步骤来配置和启动一个嵌入式的Jetty服务器: 1. 添加依赖:在项目...
文件顶部为XML文档声明,指明了使用的XML版本: ```xml ``` ##### 2.2 DTD定义 接下来是DTD(Document Type Definition)定义,用于验证XML文档的有效性: ```xml <!DOCTYPE Configure PUBLIC "-//Jetty//...
JDK7引入了一些重要的改进,如自动资源管理(try-with-resources)、新的集合类型、多线程模型的优化等,这些都使得Jetty在JDK7下运行更加高效和稳定。 2. 安装与配置:下载Jetty的对应JDK7的版本后,解压到本地...
2017年发布的9.4.6版本是该系列的一个稳定版本,提供了多项改进和修复,适用于各种大小的Web应用程序。以下是关于Jetty 9.4.6的一些关键知识点: 1. **Servlet容器**:Jetty是一个实现了Java Servlet和JavaServer ...
9. **多线程模型**:Jetty采用高效的线程池模型处理并发请求,避免了传统的Servlet容器可能遇到的线程阻塞问题。 10. **HTTP/2支持**:Jetty 9.x版本开始支持HTTP/2协议,提供了更高效的数据传输和资源加载能力。 ...
- **社区支持**:两者都拥有活跃的社区支持,但Tomcat由于更广泛的使用范围,可能拥有更多的第三方插件和文档资源。 **1.5 本章小结** Jetty是一款优秀的Web服务器和Servlet容器,以其轻量级、高性能和高度可定制...
Jetty 6.1.4还支持许多高级特性,例如WebSocket、JMX管理、HTTP压缩、SSL/TLS加密以及多线程模型的配置等。在开发过程中,你可以根据需求添加这些功能。 对于源码研究,Jetty的开源性质允许开发者深入理解其工作...
### PDF的JETTY文档知识点解析 #### 一、Jetty服务器概述与初始化流程 **1.1 Jetty服务器简介** Jetty是一个开源的、基于Java的高性能HTTP服务器及Servlet容器,广泛应用于开发和生产环境中的Java Web应用程序。...
- **下载与安装**:提供Jetty的下载地址和简单安装步骤,包括Windows和Linux下的操作。 - **启动与停止**:通过java命令快速启动和停止Jetty服务,以及使用start.jar的深入解析。 - **Windows和Linux的启动关闭...
Jetty6 指南书是一本专注于介绍Jetty 6版本的详尽教程,旨在为读者提供关于这个轻量级、高效的Web服务器和Servlet容器的深入理解。Jetty不仅是一个标准的Web容器,它的灵活性和可嵌入性使得它在许多不同的应用场景中...
对于需要高可用性的场景,可以使用Jetty的集群功能,通过多个Jetty实例协同工作来提高系统的可靠性和性能。 #### 十三、性能优化 **13.1 线程池** 合理配置线程池的大小可以显著提高服务器的并发处理能力。 **...
3. **HTTP协议实现**:Jetty提供了自己的HTTP服务器实现,这通常包括http.jar和jetty-server.jar等文件,它们负责处理HTTP请求和响应的细节。 4. **线程模型**:Jetty采用高效的线程模型,如NIO(非阻塞I/O)或...
4. **线程模型优化**:Jetty使用了一种名为“NIO2”的高效I/O模型,它减少了线程上下文切换,提高了并发处理能力。 5. **嵌入式使用**:Jetty可以很容易地被嵌入到其他Java应用程序中,无需额外的服务器进程,这...
3. **线程模型**:i-jetty采用多线程模型来处理并发请求,确保高效率和性能。通常,它会维护一个线程池,当有新的请求到来时,从线程池中取出线程来处理请求。 4. **插件架构**:i-jetty支持插件机制,允许开发者...
- 支持多线程模型,确保高并发性能。 - 具有轻量级架构,快速启动和低内存占用。 2. **Jetty 的特点** - 小巧:Jetty 体积小,启动速度快,适合快速部署和开发环境。 - 灵活:可以通过XML配置文件进行定制,...
- 通过实践,开发者可以深入了解Jetty如何为微服务提供稳定、高效的运行环境。 以上是关于“jetty简单启动web服务第二版”的详细说明,通过学习这些知识点,你可以更好地理解和使用Jetty来构建和管理微服务。在...
4. **性能优化**:Jetty团队不断进行性能调优,9.4.2版本可能包含更快的请求处理速度、内存使用优化以及更好的多线程模型。 5. **安全增强**:Jetty提供了安全的HTTP会话管理、SSL/TLS支持以及与JAAS(Java ...
- **从 Jetty 官网下载**:访问官方网站找到相应的配置文件,根据实际情况进行修改。 - **手动创建配置文件**:可以复制示例配置文件的内容,并根据实际需求进行调整。 2. **示例配置文件内容** 以下是一个典型...
- **高性能:** 通过优化的多线程模型和高效的HTTP处理,Jetty能够快速响应请求,提供高性能的Web服务。 - **灵活性:** Jetty允许自定义配置,支持多种协议(如HTTP/1.x、HTTP/2和WebSocket),并且可以方便地与...
在提供的压缩包文件`testThread`中,可能包含了一个简单的多线程Socket通信示例,演示了如何处理并发客户端请求。实际应用中,这样的代码可以作为基础,进一步集成Web Service调用来实现更复杂的业务逻辑,比如从...