`
lyunabc
  • 浏览: 528476 次
  • 性别: Icon_minigender_2
社区版块
存档分类
最新评论

上传下载加载的哲学思考

 
阅读更多

1 上传下载加载的哲学认知

“在线新华字典”对上传、下载、装载三个词的解释都是没有,这些词汇是在计算机网络出现之后才出现的一组行为词汇。

上传在“百度百科”中的解释是“上传就是将信息从个人计算机(本地计算机)传递到中央计算机(远程计算机)系统上,让网络上的人都能看到。将制作好的网页、文字、图片等发布到互联网上去,以便让其他人浏览、欣赏。这一过程称为上传。”

下载在“百度百科”中的解释是下载(xià zài(DownLoad) 是通过网络进行传输文件,把互联网或其他电子计算机上的信息保存到本地电脑上的一种网络活动。下载可以显式或隐式地进行,只要是获得本地电脑上所没有的信息的活动,都可以认为是下载,如在线观看。广义上说,凡是在屏幕上看到的不属于本地计算机上的内容,皆是通过“下载”得来。狭义上人们只认为那些自定义了下载文件的本地磁盘存储位置的操作才是“下载”。“下载”的反义词是“上传”。

加载在“百度百科”中的解释是在计算机相关领域,简单地说就是把硬盘上的有用程序调到内存中的过程叫做加载。因为所有有软件要运行必须加载到内存,加载就是把需要的文件及信息读取到内存中去,一般在启动程序或安装程序时会有加载。

上传、下载、加载是哲学中物质运动6种基本形式,即创建、消亡、增加、减少、变化、位移中的位移运动的一种在计算机领域的称谓,即上传、下载、加载的本质是位移运动。上传是物质从本地空间到远端空间的位移、下载是物质从远端空间到本地空间的位移、加载是物质从静态存贮空间向动态运行空间的位移。

作为位移运动有两边各三个基本要素,两边是位移目的、位移源,位移目的三个要素是接收物、接收载体、接收源,位移源的三个要素发送物、发送载体、物本身,位移的过程分三段(1)双方建立位移关系;(2)一发一收至到完成;(3)位移关系消亡。所以上传、下载、加载不管采用什么样的算法和协议,其基本过程都遵守位移的过程规则。

2 程序中上传的认知

上传分为Web上传和Ftp上传,前者直接通过点击网页上的链接即可操作,后者需要专用的FTP工具。

2.1 WEB上传

即通过浏览器来上传文件。  

1、通过浏览器上传文件,按照“操作向导”一步步操作完成,用户无须培训;  2、通过分配用户权限发布课件,简单,安全;  

3、支持断点续传,支持大文件上传;  

4、上传文件属性(格式,上传时间,人员等)自动生成,方便快捷;  

5WEB上传需要有一定的网页内容支持(包括上面所说的很多功能。) 

2.2 FTP上传

简称文件传输协议,通过FTP上传。  

1、上传之前,需要安装专业上传软件,并对软件加以学习,用户需要学习上传软件;  

2、需要建立FTP服务器及配置设置,专业性强;  

3、支持断点续传,无需重新上传,支持大文件上传;  

4FTP上传后,需要从后台手工输入文件属性,费时费力;  

5、但FTP上传具有WEB上传绝无仅有的优势,就是可以批量上传、批量整理,不受太多限制。

2.3 大文件上传处理机制

基于WEB的文件上传可以使用FTPHTTP两种协议,用FTP的话虽然传输稳定,但安全性是个严重的问题,而且FTP服务器读用户库获取权限,这样对于用户使用来说还是不太方便。剩下只有HTTP。在HTTP中有3种方式,PUTWEBDAVRFC1867,前2种方法不适合大文件上传,目前我们使用的web上传都是基于RFC1867标准的HTML中基于表单的文件上传。

2.3.1 RFC1867标准要点

(1) 带有文件提交功能的HTML表单

现有的HTML规范为INPUT元素的TYPE属性定义了八种可能的值,分别是:CHECKBOX HIDDENMAGEPASSWORDRADIORESETSUBMITTEXT。另外,当表单采用POST方式的时候,表单默认的具有“application/x-www-form-urlencoded”的ENCTYPE属性。  

RFC1867标准对HTML做出了两处修改:(1)为INPUT元素的TYPE属性增加了一个FILE选项。(2INPUT标记可以具有ACCEPT属性,该属性能够指定可被上传的文件类型或文件格式列表。  

另外,本标准还定义了一种新的MIME类型:multipart/form-data,以及当处理一个带有ENCTYPE="multipart/form-data" 并且/或含有<INPUT type="file">的标记的表单时所应该采取的行为。

(2) 文件传输延迟  

在某些情况下,在确实准备接受数据前,服务器先对表单数据中的某些元素(比如说用户名,账号等)进行验证是推荐的做法。但是,经过一定的考虑后,我们认为如果服务器想这样做的话,最好是采用一系列的表单,并将前面所验证过的数据元素作为“隐藏”字段传回给客户端,或者是通过安排表单使那些需要验证的元素先显示出来。这样的话,那些需要做复杂的应用的服务器可以自己维持事务处理的状态,而那些简单的应用的则可以实现得简单些。  

HTTP协议可能需要知道整个事务处理中的内容总长度。即使没有明确要求,HTTP客户端也应该提供上传的所有文件的内容总长度,这样一个繁忙的服务器就能够判断文件的内容是否是过大以至于将不能完整地处理,从而返回一个错误代码并关闭该连接,而不用等到接受了所有的数据才进行判断。目前一些现有的CGI应用对所有的POST事务都需要知道内容总长度。  

如果INPUT标记含有一个MAXLENGTH属性,客户端可以将这个属性值看作是服务器端所能够接受的传送文件的最大字节数。在这种情况下,服务器能够在上传开始前,提示客户端在服务器上有多少空间可以用来进行文件上传。但是应该引起注意的是,这仅仅是一个提示,在表单被创建后和文件上传前,服务器的实际需求可能会发生改变。  

在任何情况下,如果接受的文件过大的话,任何一个HTTP服务器都有可能在文件传输的过程中中断传输。

(3) 传输二进制数据的其他解决办法  

有些人曾经建议使用一种新的MIME类型"aggregate",比如说aggregate/mixed 或是content-transfer-encoding ""来描述那些不确定长度的二进制数据,而不是靠分解为多个部分来表示。虽然我们并不反对这么做,但这需要增加额外的设计和标准化工作来让大家接受并理解"aggregate"。从另一方面来说,"分解为多部分"的机制工作得很好,能够非常简单的在客户发送端和服务器接受端加以实现,而且能像其他一些综合处理二进制数据的方式一样高效率地工作。

2.3.2 RFC1867标准两种方式    

(1) 一次性得到上传的数据,然后分析处理

看了N多代码之后发现,目前无组件程序和一些COM组件都是使用Request.BinaryRead方法。一次性得到上传的数据,然后分析处理。这就是为什么上传大文件很慢的原因了,IIS超时不说,就算几百M文件上去了,分析处理也得一阵子。  

(2) 2.一边接收文件,一边写硬盘

了解了一下国外的商业组件,比较流行的有Power-WebAspUpload,ActiveFile,ABCUpload,aspSmartUpload,SA-FileUp。其中比较优秀的是ASPUPLOADSA-FILE,他们号称可以处理2G的文件(SA-FILE EE版甚至没有文件大小的限制),而且效率也是非常棒,难道编程语言的效率差这么多?查了一些资料,觉得他们都是直接操作文件流。这样就不受文件大小的制约。但老外的东西也不是绝对完美,ASPUPLOAD处理大文件后,内存占用情况惊人。1G左右都是稀松平常。至于SA-FILE虽然是好东西但是破解难寻。然后发现2.NET上传组件,Lion.Web.UpLoadModuleAspnetUpload也是操作文件流。但是上传速度和CPU占用率都不如老外的商业组件。  

2.4 JAVA的上传组件

(1) SmartUpload 用的最多的一个组件,已经不再更新了,可以实现上传和下载  

(2) FileUpload Apache实现的文件上传组件,功能齐备  

(3) J2KUpload java2000实现的文件上传组件,全部使用内存,适合多个不超过10M的小文件

3 程序中下载的认知

下载形式分类:HTTP下载方式、BT下载方式、cdn专用下载器、媒体下载。

3.1.1 HTTP下载

FTP专门用来下载,而HTTP的主要工作是用来浏览网页,不过也能用来下载。这两种下载方式的原理并不复杂,就是用户按照一定的规则(协议)和提供文件的服务器取得联系并将文件搬到自己的计算机中来。FTP下载方式最古老,在没有WWW的日子里,FTP就已经广为使用了。HTTP出现的较晚,但现在也应用的相当广泛。其实,如果你仅仅是为了下载而下载,那么你完全没必要把他们分的那么清,这两种使用的下载方式、下载工具几乎是一模一样的。在进行FTP或者HTTP下载之前你必须获得有效的资源链接或者服务器地址。

3.1.2 BT下载

就使用上来说,BT的使用可以说极为简单,甚至比PUB下载还要简单的多。BT的使用没那么多技巧,你只要安装好客户端,下载好种子就能马上开始下载了。就单一文件下载速度而言,BT也具有很大的优势,如果下载的人够多,能轻轻松松的到达50K以上甚至100k200K或者更高。和PUB比起来最本质的就是BT是下载的人越多越快(这是所有P2P软件的本质),PUB是下载的人越多越慢,设想一部非常经典的大片 下载

同时在BTPUB上上演,同时有很多人下载,结果如何不言而喻了。BT是一个文件分发协议,它通过URL识别内容并且和网络无缝结合。它对比HTTP/FTP协议,MMS/RTSP流媒体协议等下载方式的优势在于,一个文件的下载者们下载的同时也在不断互相上传数据,使文件源(可以是服务器源也可以是个人源,一般特指第一个做种者或种子的第一发布者)可以在增加很有限的负载之情况下支持大量下载者同时下载,所以BTP2P传输方式也有“下载的人越多,下载的速度越快”这种说法。

3.1.3 CDN下载

CDN空间意指利用CDN技术嵌入传统虚拟主机,让传统虚拟主机功能倍增的一种空间系统。

它是通过在现有的Internet中增加一层新的网络架构,CDN,智能域名解析,负载均衡系统等多种网络新技术结合体的产物。给传统虚拟主机带来概念性的变革,是目前虚拟主机的一种新技术应用。为用户提供高性能、高价格比的虚拟主机技术,帮助用户用小的投资使自己经营的网站拥有大型网站才能享受的运行技术,二代概念的虚拟主机系统,是将系统上运行的空间都采用大站的运行标准,让所有的中小网站都能享有大网站的待遇,不管在何时何地访问都是正常快速的,真正实现小网站有大作为。

4 程序中加载的认知

无论是exe程序、class程序、doc文件都需要加载到内存中才能运行起来,比如js下载到本地后,通过eval可以将其加载到内存中才能运行起来。在这里我们以class程序加载classloader为例来说明对程序加载的认知。

4.1 什么是类加载器?

与普通程序不同的是,Java程序(class文件)并不是本地的可执行程序。当运行Java程序时,首先运行JVMJava虚拟机),然后再把Java class加载到JVM里头运行,负责加载Java class的这部分就叫做Class Loader。  JVM本身包含了一个ClassLoader称为Bootstrap ClassLoader,和JVM一样,BootstrapClassLoader是用本地代码实现的,它负责加载核心JavaClass(即所有java.*开头的类)。另外JVM还会提供两个ClassLoader,它们都是用Java语言编写的,由BootstrapClassLoader加载;其中Extension ClassLoader负责加载扩展的Javaclass(例如所有javax.*开头的类和存放在JREext目录下的类),ApplicationClassLoader负责加载应用程序自身的类。  

当运行一个程序的时候,JVM启动,运行bootstrapclassloader,该ClassLoader加载java核心APIExtClassLoaderAppClassLoader也在此时被加载),然后调用ExtClassLoader加载扩展API,最后AppClassLoader加载CLASSPATH目录下定义的Class,这就是一个程序最基本的加载流程。

4.2 什么时候加载类?

什么时候JVM会使用ClassLoader加载一个类呢?当你使用java去执行一个类,JVM使用ApplicationClassLoader加载这个类;然后如果类A引用了类B,不管是直接引用还是用Class.forName()引用,JVM就会找到加载类AClassLoader,并用这个ClassLoader来加载类BJVM按照运行时的有效执行语句,来决定是否需要装载新类,从而装载尽可能少的类,这一点和编译类是不相同的。

似乎JVM自身的ClassLoader已经足够了,为什么我们还需要创建自己的ClassLoader呢?因为JVM自带的ClassLoader只是懂得从本地文件系统加载标准的java class文件,如果编写你自己的ClassLoader,你可以做到:  

1)在执行非置信代码之前,自动验证数字签名 

2)动态地创建符合用户特定需要的定制化构建类  

3)从特定的场所取得java class,例如数据库中  

事实上当使用Applet的时候,就用到了特定的ClassLoader,因为这时需要从网络上加载java class,并且要检查相关的安全信息。  

目前的应用服务器大都使用了ClassLoader技术,即使你不需要创建自己的ClassLoader,了解其原理也有助于更好地部署自己的应用。 当你决定创建你自己的ClassLoader时,需要继承java.lang.ClassLoader或者它的子类。在实例化每个ClassLoader对象时,需要指定一个父对象;如果没有指定的话,系统自动指定ClassLoader.getSystemClassLoader()为父对象。所以当创建自己的Class Loader时,只需要重载findClass()这个方法。

4.3 卸载? 重载?

当一个javaclass被加载到JVM之后,它有没有可能被卸载呢?我们知道Win32FreeLibrary()函数,Posixdlclose()函数可以被调用来卸载指定的动态连接库,但是Java并没有提供一个UnloadClass()的方法来卸载指定的类。  

Java中,java class的卸载仅仅是一种对系统的优化,有助于减少应用对内存的占用。既然是一种优化方法,那么就完全是JVM自行决定如何实现,对Java开发人员来说是完全透明的。  

在什么时候一个java class/interface会被卸载呢?事实上我们关心的不是如何卸载类的,我们关心的是如何更新已经被加载了的类从而更新应用的功能。JSP则是一个非常典型的例子,如果一个JSP文件被更改了,应用服务器则需要把更改后的JSP重新编译,然后加载新生成的类来响应后继的请求。  

其实一个已经加载的类是无法被更新的,如果你试图用同一个ClassLoader再次加载同一个类,就会得到异常(java.lang.LinkageError: duplicate classdefinition),我们只能够重新创建一个新的ClassLoader实例来再次加载新类。至于原来已经加载的类,开发人员不必去管它,因为它可能还有实例正在被使用,只要相关的实例都被内存回收了,那么JVM就会在适当的时候把不会再使用的类卸载。  

使用线程上下文类加载器, 可以在执行线程中, 抛弃双亲委派加载链模式, 使用线程上下文里的类加载器加载类.   

典型的例子有, 通过线程上下文来加载第三方库jndi实现, 而不依赖于双亲委派.大部分java app服务器(jboss, tomcat..)也是采用contextClassLoader来处理web服务。当然, 好东西都有利弊. 使用线程上下文加载类, 也要注意, 保证多根需要通信的线程间的类加载器应该是同一个, 防止因为不同的类加载器, 导致类型转换异常(ClassCastException).

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics