Continuation 异步化机制(转)

Jetty 的 Continuation 机制

讨论 Jetty 的 Continuation 机制,首先需要提到 Ajax 技术,Ajax 技术是当前开发 Web 应用的非常热门的技术,也是 Web 2.0 的一个重要的组成部分。Ajax 技术中的一个核心对象是 XMLHttpRequest 对象,这个对象支持异步请求,所谓异步请求即是指当客户端发送一个请求到服务器的时候,客户端不必一直等待服务器的响应。这样就不会造成整个页面的刷新,给用户带来更好的体验。而当服务器端响应返回时,客户端利用一个 Javascript 函数对返回值进行处理,以更新页面上的部分元素的值。但很多时候这种异步事件只是在很小一部分的情况下才会发生,那么怎么保证一旦服务器端有了响应之后客户端马上就知道呢,我们有两种方法来解决这个问题,一是让浏览器每隔几秒请求服务器来获得更改,我们称之为轮询。二是服务器维持与浏览器的长时间的连接来传递数据,长连接的技术称之为Comet。

大家很容易就能发现轮询方式的主要缺点是产生了大量的传输浪费。因为可能大部分向服务器的请求是无效的,也就是说客户端等待发生的事件没有发生,如果有大量的客户端的话,那么这种网络传输的浪费是非常厉害的。特别是对于服务器端很久才更新的应用程序来讲,比如邮件程序,这种浪费就更是巨大了。并且对 Server 端处理请求的能力也相应提高了要求。如果很长时间才向 Server 端发送一次请求的话,那么客户端就不能的得到及时的响应。

如果使用 Comet 技术的话,客户端和服务器端必须保持一个长连接,一般情况下,服务器端每一个 Servlet 都会独占一个线程,这样就会使得服务器端有很多线程同时存在,这在客户端非常多的情况下也会对服务器端的处理能力带来很大的挑战。

Jetty 利用 Java 语言的非堵塞 I/O 技术来处理并发的大量连接。 Jetty 有一个处理长连接的机制:一个被称为 Continuations 的特性。利用 Continuation 机制,Jetty 可以使得一个线程能够用来同时处理多个从客户端发送过来的异步请求,下面我们通过一个简化的聊天程序的服务器端的代码来演示不使用 Continuation 机制和使用 Continuation 的差别。


Continuation 机制

[java] view plaincopy在CODE上查看代码片派生到我的代码片
public class ChatContinuation extends HttpServlet{

public void doPost(HttpServletRequest request, HttpServletResponse response){
postMessage(request, response);
}

private void postMessage(HttpServletRequest request, HttpServletResponse response)
{
HttpSession session = request.getSession(true);
People people = (People)session.getAttribute(session.getId());
if (!people.hasEvent())
{
Continuation continuation =
ContinuationSupport.getContinuation(request, this);
people.setContinuation(continuation);
continuation.suspend(1000);
}
people.setContinuation(null);
people.sendEvent(response);
}
}
大家注意到,首先获取一个 Continuation 对象,然后把它挂起 1 秒钟,直到超时或者中间被 resume 函数唤醒位置,这里需要解释的是,在调用完suspend 函数之后,这个线程就可处理其他的请求了,这也就大大提高了程序的并发性,使得长连接能够获得非常好的扩展性。

如果我们不使用 Continuation 机制,那么程序就如 清单 3 所示:


不使用 Continuation 机制

[java] view plaincopy在CODE上查看代码片派生到我的代码片
public class Chat extends HttpServlet{
public void doPost(HttpServletRequest request, HttpServletResponse response){
postMessage(request, response);
}

private void postMessage(HttpServletRequest request, HttpServletResponse response)
{
HttpSession session = request.getSession(true);

People people = (People)session.getAttribute(session.getId());

while (!people.hasEvent())
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
people.setContinuation(null);
people.sendEvent(response);
}
}
大家注意到在等待事件发生的时间里,线程被挂起,直到所等待的事件发生为止,但在等待过程中,这个线程不能处理其他请求,这也就造成了在客户端非常多的情况下服务器的处理能力跟不上的情况。下面我们解释一下 Jetty 的 Continuation 的机制是如何工作的。

为了使用 Continuatins,Jetty 必须配置为使用它的 SelectChannelConnector 处理请求。这个 connector 构建在 java.nio API 之上,允许它维持每个连接开放而不用消耗一个线程。当使用SelectChannelConnector 时,ContinuationSupport.getContinuation() 提供一个SelectChannelConnector.RetryContinuation 实例(但是,您必须针对 Continuation 接口编程)。当在RetryContinuation 上调用suspend() 时,它抛出一个特殊的运行时异常 -- RetryRequest,该异常传播到 servlet 外并且回溯到 filter 链,最后被SelectChannelConnector 捕获。但是不会发送一个异常响应给客户端,而是将请求维持在未决 Continuations 队列里,则 HTTP 连接保持开放。这样,用来服务请求的线程返回给 ThreadPool,然后又可以用来服务其他请求。暂停的请求停留在未决 Continuations 队列里直到指定的过期时间,或者在它的 Continuation 上调用resume() 方法。当任何一个条件触发时,请求会重新提交给 servlet(通过 filter 链)。这样,整个请求被"重播"直到 RetryRequest 异常不再抛出,然后继续按正常情况执行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Fixed Point Continuation(FPC)是一种用于非线性方程求解的迭代算法。FPC算法是一种二分法的变种,可以用来求解非线性方程组,函数最小值以及非线性最小二乘等问题。 下面是一个用matlab实现Fixed Point Continuation算法的例子: ```matlab function [x, fval, iter] = FPC(f, dfdx, x0, alpha, beta, tol, maxiter) % Fixed Point Continuation algorithm for solving nonlinear equations % f: function handle of the nonlinear equation % dfdx: function handle of the derivative of f % x0: initial guess % alpha, beta: continuation parameters % tol: tolerance for stopping criterion % maxiter: maximum number of iterations % initialization iter = 0; x = x0; fval = f(x); while abs(fval) > tol && iter < maxiter % compute new guess using Fixed Point Iteration x_new = x - alpha*fval / dfdx(x) + beta*(x - x0); fval_new = f(x_new); if abs(fval_new) < abs(fval) % accept new guess x = x_new; fval = fval_new; else % decrease alpha and beta and try again alpha = alpha / 2; beta = beta / 2; end iter = iter + 1; end if iter == maxiter warning('FPC algorithm did not converge within maximum number of iterations'); end end ``` 该函数接受以下输入参数: - `f`: 非线性方程的函数句柄 - `dfdx`: 非线性方程的导数函数句柄 - `x0`: 初始猜测 - `alpha` 和 `beta`: continuation参数,用于控制迭代步长和收敛速度 - `tol`: 停止迭代的容差 - `maxiter`: 最大迭代次数 该函数返回以下输出参数: - `x`: 迭代收敛的解 - `fval`: `x`处的函数值 - `iter`: 迭代次数 该算法使用Fixed Point Iteration来计算新的猜测,如果新的猜测的函数值比旧的猜测更接近于零,则接受新的猜测。否则,将减小`alpha`和`beta`并重试。因此,该算法可以自适应地调整迭代步长和收敛速度,以便在最小的迭代次数内找到解。 下面是一个使用上述函数来解决非线性方程的例子: ```matlab % define the nonlinear equation f = @(x) x^3 - x^2 - 1; dfdx = @(x) 3*x^2 - 2*x; % set initial guess and continuation parameters x0 = 1; alpha = 1; beta = 0; % set stopping criterion and maximum number of iterations tol = 1e-6; maxiter = 100; % solve the nonlinear equation using FPC algorithm [x, fval, iter] = FPC(f, dfdx, x0, alpha, beta, tol, maxiter); % display the solution and number of iterations fprintf('Solution: x = %f\n', x); fprintf('Number of iterations: %d\n', iter); ``` 该程序将输出以下结果: ``` Solution: x = 1.465571 Number of iterations: 26 ``` 该算法收敛于非线性方程的解,并且只需要26次迭代即可达到所需的精度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值