Squid Web Cache Wiki

Squid Web Cache 文档

🔗 特性:异步调用原生支持

🔗 设计草图

本节总结了异步调用接口的设计思路。此处讨论的内容只有一小部分已实现,因此预计会有许多变动。

🔗 主循环

高层概览:主循环将持续触发所有异步调用,直到没有调用为止。然后,它将从基于时间的事件队列中获取最大等待时间,并让“select”探测文件描述符。下面的代码草图概述了一次主循环迭代。

timeout = TheEvents.checkpoint();
TheCalls.fireAllCalls();
TheSelect.scan(timeout);

更现实的情况:除了上述内容,如果触发了异步调用,事件队列必须重新检查,因为调用可能耗时足够长,以至于新事件变得就绪。同样,下面的代码片段是单次主循环迭代。

do {
    timeout = TheEvents.checkpoint();
    something_has_changed = not TheCalls.empty();
    TheCalls.fire();
} while (something_has_changed);

TheSelect.scan(timeout);

🔗 触发单次调用

在触发异步调用之前,Squid 会准备捕获调用异常。如果调用本身触发失败(例如,事件回调数据无效),Squid 将停止处理该调用。如果捕获到异常,将调用调用异常处理器。

    try {
        if (!call->fire())
            return;
    }
    catch (const exception &e) {
        call->handleException(e);
    }
    call->end();

所有异步调用的触发方式都相同。各个调用类型提供特定于调用的调试信息(格式类似),使用存储的参数调用所需代码,并定制异常处理。

实际代码也可能使用 catch(…) 子句捕获其他异常。

🔗 回调

回调是进行未来调用所需的信息。回调通常在 Squid 中用于向作业或模块注册,以接收关于重要事件的未来更新或其他异步通知。

它可以被视为一个未完成的调用:已知调用目标地址和可能的某些参数,但调用的时间和可能的其他参数未知,必须由调用者确定。

初始实现不会优化回调表示,而是仅使用调用(带有某些未设置的参数)作为回调。

🔗 调用类型

调用目标种类决定了调用类型。支持的目标包括:AsyncJob 对象方法、其他对象方法和全局静态函数。

AsyncJob 调用可能会这样实现其公共方法。

    bool JobCall::fire() {
        AsyncJob *job = dynamic_cast<AsyncJob*>(theObject);
        if (job pointer is not valid) {
            debugs(section, level, "NOT Calling " << className << "::"
                << methodName << " method ...");
            return false;
        }
    
        debugs(section, level, "Entering " << className << "::" <<
            methodName << " method [" >> job->status () >> "]");
        (job->*)(theMethod)(...)
        return true;
    
    }
    
    void JobCall::end()
    {
    
        if (job->done()) {
            debug("Ending job [" >> job->status () >> "]");
            job->swanSing();
            delete job;
            debug("The " << className << "::" << methodName
                << " method  ended the job [" >> (void*)job >> "]");
            return;
        }
        debug("Exited " << className << "::" << methodName <<
            " method [" >> job->status () >> "]");
    }

实际的 JobCall 代码将使用更多调试,并可能利用更多的 ObjectCall(即其父类)功能。

Comm 模块可能会提供自己的便捷类来处理“通知您的文件描述符已准备好”之类的调用。

🔗 是什么创建了异步调用?

在 TheCalls 队列初始化后,任何代码都可以随时排队一个异步调用。例如,以下任何调用都可能导致新的异步调用创建。

TheEvents.checkpoint();  // when the event(s) time has come
TheCalls.fireAll();      // when a call handler needs to call
TheSelect.scan(timeout); // when descriptors are ready

🔗 挑战

将会有模板、宏和/或代码生成的类来处理任意的调用目标地址以及带有零、一、二或三个参数(至少)的调用。设计一组简单而高效的包装器而不使用像 Boost 这样的基于模板的库将很棘手。

类别:功能

导航:站点搜索站点页面类别🔼 向上