什么网站开发外贸客户,关于网页的毕业设计题目,北大青鸟网站建设,网站平台建设简介 由于浏览器禁止跨域的XMLHTTP调用#xff0c;所有的Ajax网站都必须有一个服务端代理来从外部域比如Flickr或者Digg来抓去内容。对客户端Javascript代码来说#xff0c;一个XMLHttp的调用将请求传递给宿主在相同域里的服务端代理#xff0c;然后由代理来从外部服务器上下… 简介 由于浏览器禁止跨域的XMLHTTP调用所有的Ajax网站都必须有一个服务端代理来从外部域比如Flickr或者Digg来抓去内容。对客户端Javascript代码来说一个XMLHttp的调用将请求传递给宿主在相同域里的服务端代理然后由代理来从外部服务器上下载内容并回传给客户端。通常所有从外部服务器获取内容的Ajax站点都采用这种代理方案除了一些罕见的使用JSONP的人。当网站上的许多组件正在从外部域下载内容时这样的代理将会被大量地调用。所以当代理开始被百万次地调用时它将变成一个可扩展的问题。另外一个页面整体的负载均衡很大程度上依赖于当代理向页面提供内容时它的性能。这篇文章我们来看看我们如何能将传统的Ajax代理变得更快异步持续提供内容流从而使其更具扩展性。 Ajax代理 进行时 当你访问Pageflakes.com时你可以看到这样的代理正在工作。你将看到许多不同的内容例如天气预报、flickr图片、YouTuBe的视频以及RSS等像一个个部件一样从许多不同的外部域中被加载。所有这些加载都需要使用一个内容代理。该内容代理在最近一个月为差不多42.3百万的URL提供过服务。使它既快又有扩展性是对我们相当大的挑战有时内容代理需要提供兆字节数据的服务这更加提高了这些挑战的高度。因为这样的代理会被大量的调用如果我们能够为每个调用平均节约大概100ms我们每个月就可以为下载、上传、处理的时间节约大概4.23百万秒。这大概1175人时都被全世界百万人在浏览器前等待下载内容而浪费掉了。 这样的内容代理将外部服务器的URL作为一个查询参数。它从这些URL下载内容然后将这些内容作为响应回传给服务器。 图片内容代理像一个中间人一样在浏览器和外部域之间工作。 上面的时间线显示了一个请求如何到达服务器然后服务器向外部服务器发出请求下载响应并将它传输给客户端。从代理到浏览器的响应箭头比从外部服务器到代理的箭头更长这是因为通常一个代理服务器的宿主环境比用户的互联网连接有更快的下载速度。 一个基本的代理 这种内容代理也同样存在与我的开源Ajax网站——Dropthings.com中。你可以去CodePlex看它的代码是如何实现这样一个代理的。 下面是一个非常简单同步没有流的阻塞代理。 尽管它显示了通常的原则但它没有接近一个真实的代理因为 1 他是一个同步代理因此没有可扩展性。每一个对该Web方法的调用都导致Asp.net线程处于等待状态直到对外部URL的调用完成。 2 它是非流式的。它第一次从服务器上下载整个内容将内容存储在一个字符串中然后向浏览器更新整个内容。如果你点击一个MSDN Feed URL它将从服务器下载220KB的巨大的RSS XML将它存储到一个220KB的长字符串中总得来说是.net内置String类型的双倍大小并且都是Unicode字符然后将这220KB写到asp.net响应对象(Response)的缓冲区(buffer)中并将另外的220KB的UTF8的字节数组存储在内存中。然后那220KB将被传递到IIS以便可以传输到浏览器。 3 它没有在服务端存产生一个正确的响应头来缓存响应。它也没有从源文件中提供重要的头部例如Content-Type。 4 如果一个外部URL提供对内容的GZIP压缩它解压内容到一个字符串来表示因此它浪费了服务器的内存。 5 它没有在服务端缓存内容。因此重复对相同外部URL的调用也将从外部URL重新下载数据因此浪费了你服务端的带宽。 我们需要一个异步的streaming proxy当它从外部域服务器下载后传输内容到浏览器。因此它将从外部服务器下载字节流到一个小块儿中并且直接将其传输到浏览器。结果是在调用Web Service之后浏览器将看到一个持续的字节传输。当内容已经完全从服务器上下载下来后将没有延迟。 一个更好的代理 之前我展示了复杂的基于流代理的代码让我们讨论一个改进式的方案。让我们建立一个比上面更好的内容代理。上面的代理是一个同步并且非流式但没有其他问题的代理。我们将构建一个命名为Regular.ashx的HTTP Handler它将把URL作为查询参数。它也将缓存作为一个查询参数该查询参数将用来产生一个正确的响应头来在浏览器上缓存内容。因此它将一次又一次减少浏览器重复下载相同内容的时间。 上面的代理主要增强了两点功能 l 它允许服务端缓存内容。在一段时间内来自不同浏览器的相同URL请求在服务端将不会再次下载而是从服务端缓存中获取数据。 l 它产生一个正确的输出响应头可以让内容缓存到浏览器端。 l 它没有在内存中解压下载的内容。它保持原始字节流的完整。它节省了内存。 l 它用一种无缓冲的形式发送数据这意味着asp.net的Response对象没有缓冲响应因此节约了内存。 然而这是一个“阻塞”式的代理。 更好的代理——基于流 我们需要构建一个基于流的异步代理来提供更好的性能。下面的图阐述了这是为什么 图片持续的流式代理 就像你所看到的当服务器下载内容的时候数据从服务器被发送回浏览器服务端下载的延时被消除。因此如果服务器花300ms来从一个外部资源下载内容然后花700ms将它发送回服务器你就可以在服务器和浏览器之间节约300ms的网络延迟(因为异步就会边下载边传输数据流)。这种方案在当外部服务器提供的内容非常慢并且需要花相当长的一段时间来提供内容时效果非常好。外部站点越慢采用这种持续流式代理你节约的时间就越多。当你的站点很远时这比起阻塞式的方案在性能上是一个很大的提升。 这种持续式的代理方案是 l 用一个特殊的线程读取器线程来从外部服务器读取一个8KB的字节块目的是使其不阻塞。 l 将读取到的块存储在一个被称为管线流的内存队列里面。 l 从该队列里将块写到Asp.net的Response对象。 l 如果队列完成使其处于等待状态直到更多的字节被读取器线程下载。 这种管线流需要是线程安全的并且它需要支持“阻塞式”的读取。“阻塞式”的读取这意味着如果一个线程尝试读取一个块儿并且流是空的将暂停该线程直到另一个线程在流上写完东西。一旦在流上的一个写操作发生了它将恢复读线程并且允许它继续读。我从CodeProjectarticle by James Kolpack那里获得了管线流的代码并且测试了并确信它有很高的性能支持存储字节块而不是单个字节支持等待超时等等。 我将普通的代理(阻塞、同步、下载完所有之后才传输数据)和流式代理(从外部服务器到浏览器持续传输数据)做了一些对比。两个代理下载MSDN资源并且传输到浏览器。显示在下面的时间是从浏览器发出请求到代理然后回传整个响应到客户端。 这不是一个非常科学的图片并且响应的时间还取决于从浏览器到代理服务器之间连接的速度和从代理服务器到外部服务器的速度。但它显示了大部分时间里流式代理比通常的代理表现出更好的性能。 构建流式代理 构建一个性能好于普通流式代理并不是那么简单。我尝试了三种方式最终找出了最佳组合可以表现出比普通代理更好的性能。 该流式代理使用HttpWebRequest和HttpWebResponse来从一个外部服务器下载数据。它们被用来对如何读取数据取得更多得控制更具体地说是读取WebClient不提供的字节块儿。另外这里有某些对构建一个代理需要的快速、可扩展HttpWebRequest的优化。 DownloadData方法从输出流(连接到外部服务器)下载数据然后将其发送给asp.net的Response流。 这里我曾尝试了三种不同的方案。一个是现在被注释掉的叫做TransmitDataAsyncOptimized是最好的解决方案。我将解释这三种方案。DownloadData方法的目的是在发送数据之前准备asp.net的输出流。然后它使用这三种方案里的其中一种发送数据并缓存下载的字节到内存流中。 第一种方案是从连接到外部服务器的输出流中读取8192字节然后直接写到响应TransmitDataAsyncOptimized。 这里readStream是从HttpWebResponse.GetResponseStream调用返回的输出流。它从外部服务器下载。responseBuffer仅仅是用来在内存中存储整个响应一个内存流目的是我们能够缓存它。 这个方案甚至比一个通常的代理更慢。在做了一些代码级别的性能分析之后看起来写入OutputStream花费了相当长得时间因为IIS尝试发送数据到浏览器。所以这里会有网络延迟和传输数据的延迟。从频繁调用累积的网络延时到OutputStream.Write加起来显著地延迟了整个操作。 第二个方案是尝试多线程。一个从asp.net线程创建的新线程持续地从Socket读取甚至不用等待Response.OutputStream发送字节到浏览器端。主asp.net线程等待直到所有的字节被收集完成然后直接传输它们到response。 这里读取是在PipeStream上进行的而不是从asp.net线程的socket上。这里有一个新线程被催生它将数据写入PipeStream就像它从外部站点下载字节一下。结果我们有asp.net线程持续地将数据写入OutputStream并且有另外一个线程从外部服务器不断地下载数据。接下来的代码从外部服务器下载数据然后存储到PipeStream中。 这个方案的问题是仍然有很多Response.OutputStream.Write的调用发送。外部服务器发送各种不同字节数的内容有时3592字节有时8192字节并且有时仅仅501字节。它完全依赖于从你的服务器到外部服务器的连接有多快。通常微软的服务器都是非常快速的当你调用_ResponseStream.Read从MSDN读取资源的时候你总是能获得8192(缓存区的最大容量)的字节但当你连接到一个非可靠的服务器例如在澳大利亚你将无法在每次读取调用时都获得8192个字节的数据。所以你将以超过你对Response.OutputStream.Write预期调用次数而结束。所以一个更好的最终方案是介绍另一个缓冲区它将存储将写到asp.netResponse的字节并且一旦8192个字节已经准备好传输时它将自己清空缓冲区到Response.OutputStream。在这中间缓冲区将确保总是有8192个字节被发送到Response.OutputStream。 上面的方法确保一次仅有8192字节被写入asp.netResponse.Stream中。以这种方式写的次数是总字节数/8192。 用异步httphandler构建流式代理 现在我们正基于流来传输字节我们需要让这个代理“异步”让它不把持着asp.net的主线程太长时间。变成异步这意味着一旦asp.net线程向外部服务器发出一个调用它就会被释放。当外部服务器调用完成并且字节都下载完成它将从asp.net抢占一个线程然后完成执行。 当代理不是异步的时候它会使得asp.net线程很繁忙直到整个的连接以及下载操作完成。如果外部服务器响应很慢那它就没有必要持有asp.net线程太长时间。结果如果代理正对一个很慢的服务器发起太多的请求asp.net线程不久就将消耗殆尽并且你的服务器将停止响应任何新请求。 构建一个异步代理的第一步是实现IhttpAsyncHandler然后将ProcessRequest方法分成两部分BeginProcessRequest和EndProcessRequest。Begin方法将对HttpWebRequest.BeginGetResponse发出一个调用然后线程返回到asp.net的线程池。 当BeginProcessRequest调用完成并且外部服务器已经开始向我们发送响应数据asp.net会调用EndProcessRequest方法。该方法从外部服务器下载数据然后发送回浏览器端。 现在你已经拥有了它——一个快速的可扩展的持续流式的代理它总是会比通常的代理有更好的性能。 如果你正在考虑写HttpHelperAsyncState以及SyncResult类这里有一些现成的类下面是这些帮助类的代码 源代码下载地址 http://download.csdn.net/detail/yanghua_kobe/3702484转载于:https://www.cnblogs.com/wdpp/archive/2011/10/20/2386598.html