转载自 https://blog.zymlinux.net/index.php/archives/540
ATS插件开发需要提前了解ATS的插件的一些设计思想,以及系统提供的一些不同方向。我们将会介绍ATS的基础开发知识,以利于后续的插件开发课程讲解。
ATS的SDK文档,是了解ATS的核心设计、接口设计的很重要资料,甚至是老的PDF版本文档,都是非常非常有用的资料。以至于我经常建议完全不了解ATS核心代码的初学者也好好看看SDK文档,这里讲的很多基础知识,有利于对核心的深入理解。ATS的API以及核心插件接口设计是一个很庞大的工程,其设计思想我们很难一下消化掉,这里点出一些知识点供大家参考。如有纰漏、谬误之处,以SDK文档、代码注释、代码为准。
官方SDK文档
历史的SDK PDF文件
下一篇:手把手教你写plugin
HTTP Transaction
HTTP Transaction 是ATS特指http的处理流程,在ATS中,一个HTTP的请求的处理过程,叫做一个HTTP Transaction。ATS的很多API是以Transaction为核心的函数处理过程,也就赋予了这个过程以特殊的意义。在相关的API函数中,TSHttpTxn数据结构,以及以TSHttpTxn开头的API函数都是围绕这个处理流程来的。
HTTP SM
HTTP SM 是一般是指ATS的主流程状态机,在ATS中,处理的流程是通过HTTP Transaction中的函数处理的,而状态数据是存储在HTTP SM中的。ATS核心主流程就是HTTP Transaction和HTTP SM的交互过程。
HTTP session
HTTP session是指http会话,一般指一个请求交互过程,特指如客户端的一个请求,回源的一个请求,分别对应客户端和服务器端HTTP session。对照HTTP Transaction,我们对应的ATS一个用户请求引起的ATS HTTP Transaction,可以包含一个客户端 HTTP Session,0个或1个甚至多个回源 HTTP Session。
remap
remap是ATS做URL rewrite的方式,也是ATS在配置文件设计方面的特殊部分。从功能上来讲,ATS的remap更像一个精简版本的Apache Httpd的rewrite模块。remap之所以重要,是因为它定义了一个很方便的API入口,我们可以通过remap系统,编写remap插件。
Continuation
Continuation,从学术上应该是叫做Continuation的编程模型(方法),这个技术相当古老,后来微软围绕这个方案,改进出了coroutine的编程模型(方法),一定程度上来讲Continuation是整个异步回调机制的多线程事件编程基础。对应ATS中,Continuation是一个最最基础的抽象结构,后续的所有高级结构,如Action Event VC等都封装Continuation数据结构,我们先看Continuation结构的实际代码:
class Continuation: private force_VFPT_to_top
{
public:ContinuationHandler handler;Ptr mutex;LINK(Continuation, link);int handleEvent(int event = CONTINUATION_EVENT_NONE, void *data = 0) {return (this->*handler) (event, data);}Continuation(ProxyMutex * amutex = NULL);
};
Continuation主要包含:
结构非常精炼,并不代表特殊含义。
Continuation在API中的结构叫TSCont,是插件开发中最常用到的抽象之一,是多数API要求的参数结构。在插件编程中的主要用到的如blacklit-0中的代码:
TSHttpHookAdd(TS_HTTP_OS_DNS_HOOK, TSContCreate(blacklist_plugin, NULL));
这是一个hook函数,在TS_HTTP_OS_DNS_HOOK
阶段,hook进去了blacklist_plugin
(见下面代码),而blacklist_plugin
函数事实上只是一个事件处理的handler而以,这里通过TSContCreate
转化为TSCont
结构。通过这些API,插件开发者可以更关注业务流程实现,甚至都可以不用去理解ATS核心的复杂异步事件化机制,只需要照着例子来堆代码就好啦。
static int
blacklist_plugin(TSCont contp, TSEvent event, void *edata)
{TSHttpTxn txnp = (TSHttpTxn) edata;switch (event) {case TS_EVENT_HTTP_OS_DNS:handle_dns(txnp, contp);return 0;case TS_EVENT_HTTP_SEND_RESPONSE_HDR:handle_response(txnp);return 0;default:break;}return 0;
}
Action
Action是一个抽象出来的,由处理机处理的异步任务模型。这个任务是可以在异步处理环境中允许撤销的。简单的以为可以说是一个可以撤销的函数机制?
这个结构的主要用处是用来构建统一的Event系统,用在底层的iocore/中的网络以及磁盘IO等方面。当然,ATS的上层建筑更是依赖于它了。
class Action
{
public:Continuation * continuation;Ptr mutex;volatile int cancelled;virtual void cancel(Continuation * c = NULL) {if (!cancelled)cancelled = true;}void cancel_action(Continuation * c = NULL) {if (!cancelled)cancelled = true;}Continuation *operator =(Continuation * acont){continuation = acont;if (acont)mutex = acont->mutex;elsemutex = 0;return acont;}Action():continuation(NULL), cancelled(false) {}virtual ~ Action() {}
};
关于Action,有几个需要注意的地方:
Event
Event是由Event处理机返回的一种Action。是可以用来调度出去从而异步处理的任务(Action)。event是不可再入的。由于它继承自Action,因此也具有可以撤销的机制,同时更可以在收到Event后处理或不处理而再调度出去,这个很乱啊:D
Event的调度分为4种:
_every:每隔多长事件,让事件循环执行,类似cron等定时任务
class Event:public Action { public: void schedule_imm(int callback_event = EVENT_IMMEDIATE); void schedule_at(ink_hrtime atimeout_at, int callback_event = EVENT_INTERVAL); void schedule_in(ink_hrtime atimeout_in, int callback_event = EVENT_INTERVAL); void schedule_every(ink_hrtime aperiod, int callback_event = EVENT_INTERVAL); void free();
EThread *ethread;
unsigned int in_the_prot_queue:1; unsigned int in_the_priority_queue:1; unsigned int immediate:1; unsigned int globally_allocated:1; unsigned int in_heap:4; int callback_event;
ink_hrtime timeout_at; ink_hrtime period;
void *cookie;
Event(); Event *init(Continuation * c, ink_hrtime atimeout_at = 0, ink_hrtime aperiod = 0); private: void *operator new(size_t size); Event(const Event &); Event & operator =(const Event &);
public: LINK(Event, link); };
关于Event结构,有如下几点需要注意:
VC
VConnection是ATS核心、插件都常用的一种面向stream的数据抽象结构。主要可以理解为一个数据读写管道,在某些场景下,有点类似FD的效果。VConnection继承自continuation,也是会call-back到处理机处理的。这个基类是封装上层通信管道的基础。
VConnection提供关键的几个接口:
set_continuation
class VConnection:public Continuation { public:
virtual ~ VConnection();
virtual VIO *do_io_read(Continuation *c = NULL, int64_t nbytes = INT64_MAX, MIOBuffer *buf = 0) = 0; virtual VIO *do_io_write(Continuation *c = NULL, int64_t nbytes = INT64_MAX, IOBufferReader *buf = 0, bool owner = false) = 0; virtual void do_io_close(int lerrno = -1) = 0; virtual void do_io_shutdown(ShutdownHowTo_t howto) = 0;
VConnection(ProxyMutex *aMutex); virtual void set_continuation(VIO *vio, Continuation *cont); virtual void reenable(VIO *vio); virtual void reenable_re(VIO *vio);
virtual bool get_data(int id, void *data) { (void) id; (void) data; return false; } virtual bool set_data(int id, void *data) { (void) id; (void) data; return false; }
public: int lerrno; };
VConnection定义了一个可以串联的虚拟管道,可以让ATS在网络、状态机、磁盘间形成流式数据通信,是上层通信机制的很关键一环。
C API
ATS默认的API是C API,即ts.h,这是C的API,据某人说用C++程序封装出C API很强大,不明觉历。
ATS同时还有一些个非稳定的API,定义在:experimental.h
还有2个API文件,默认并没有提供给大家
C++ API
LinkIn 公司为ATS添加了一套C++的API,需要在编译的时候加 --with-cpp11api
选项configure才行。
C++ API包含:
这个API可能不够完备
ATS 插件模式
ATS 插件模板
tsxs
这个工具能够生成一些模板代码,正在整理中主HttpSM
HttpSM是指ATS的核心http流程状态机,即proxy/http/HttpSM.cc(.h)中定义的状态机,这是整个proxy业务的大状态机,所有的其他流程都是依附于(或关联于)这个状态机上的。如回源、读写cache等。当然这个文件也是目前ATS中最大的2个文件之一,以近万行的代码挑战你的能力。
HttpSM相对插件开发者来说,几乎是不可见的,因为所有的插件都是hook到整个http流程中间来的。只有想看核心代码的同学才有意义。
子状态机
所谓子状态机,其实在ATS的事件系统里,到处都是,只要是做一个稍微复杂点的异步处理必然要引入一个状态机(processor)来做,相对来说这些都比较微型化。
ATS的主HttpSM状态机并不是完全不可控制的,ATS允许你很大程度的自己定制自己的状态机,甚至绕过绝大多数HttpSM流程,这里可以参考的代码有:
iocore
IOcore系统是定义最核心的ATS基础模块,定义了底层的所有关键框架,这些模块和框架与业务系统相对独立,其中包括:
IOcore系统,代码逻辑相对隔离的还是不错的,因此各个模块是能够比较独立的理解和学习的。
proxy
Proxy模块可以说是ATS的业务逻辑,也是traffic_server的主代码所在地。
Proxy下有几个比较关键的模块:
其他各种功能,都放在proxy/目录下,这里也是功能最多、最乱的一滩子啦。
cop
cop是用来存放traffic_cop代码的,相对来说是最简单的代码啦。
mgmt
这里存放的是traffic_manager代码。其中仍有许多需要清理的老代码残渣。
lib
这里存放的是ATS的基础库,继承自原Inktomi++的仿C++标准库,ATS对外部库依赖比较少皆因这个库成型比较早,并且覆盖面比较全面。某人说这个就是C++标准库啊。话说当年(95-99年)ATS开发的时候,C++标准还在娘胎中吧?
lib下有几个关键模块:
example
存放SDK介绍的,以及未介绍的所有插件参考代码。可以放心的说,ATS能够做的场景,在这个目录下都可以找到比较接近的例子。从这里的代码开始业务编程是很好的选择。
tools
存放性能测试工具如http_load jtest工具以及状态跟踪工具tstop等
plugins
存放所有公开到主代码的插件系统代码:
doc
存放Admin手册、man手册等
rc
init脚本等
我的博客上已经有很多这样的ats安装实录了,这次的笔记有些不一样,因为它是ATS目前最新的LTS版本6.2.1的安装,写出来更多的是整理自己的思路,因为很多东西搞过不整理,过一段时间就完全忘记掉了。 安装环境: 在rMBP 15.4上上面安装了VMware Fushion 专业版8.5.1,操作系统是MacOS Sierra 10...
2011年我曾有机会精心研究了ATS Cache Module部分的大部分源码,也绘制了一些蹩脚的图片,但是对比专家和大牛的作品还相去甚远,下面的图片摘自Fall Summit 2014中的ATS committer Alan M. Carroll的ppt,仅作研读ATS源码时作参考和对照,更是对高手极致境界的尊崇和反思。...
转载自https://blog.zymlinux.net/index.php/archives/129 首先申明本人是个实实在在的菜鸟,现在也只是搭建起来ats玩玩简单的,写本文只是为了给完全的小白一个参考而已。 本人刚开始接触ats的时候,从ats安装到配置也遇到了很多基本的问题,在查阅资料解决不了的时候基本都是豪哥耐心...
THE START更新堪称轻量级MATLAB的一款软件最新版-Maplesoft Maple 2019.2 中文版。Maple是符号和数字计算环境,也是一种多范式编程语言,由Maplesoft开发,还涵盖了技术计算的其他方面,包括可视化,数据分析,矩阵计算和MATLAB连接。MapleSim工具箱添加了用于多域物理建模和代码生成的...
同学们,你们在学习他人的代码,是否见过这样的代码 def main(): def user_info(gender): 当你还是个小萌新时,你一定会认为这是个很牛逼的语法。 当你有了一点基础时,你一定会想要了解这个语法,并且尝试去使用它。 那么今天,我们便来了解这个牛语法。 有了一点点的python基础,我们来看这段代...
自从用了这些快捷键,鼓励师也不需要了,代码开发效率蹭蹭提升!!! ctrl+shift+[折叠代码 (这个比ctrl+k ctrl+l、ctrl+k ctr+j不知道好用多少倍!) ctrl+shift+]展开代码 ctrl+shift+T打开手贱不小心关掉的窗口 【推荐】ctrl+shift+O打开当前文件...
在提交代码之前,建议最好先Fetch代码下来(如果有冲突,系统会提示),然后再操作Merge到本地分支,这样做是为了避免有其他人同时修改了当前分支,如果直接用Ctrl+T(pull代码)极有可能覆盖本地分支最新代码,安全起见先Fetch代码(Ctrl+Alt+Shift+1)——所谓:小心驶得万年船!...
每次复制代码时,如果代码里有 // 这样的注释就容易让格式乱掉,通过下面的设置就可以避免这种情况。 粘贴代码时取消自动缩进 VIM在粘贴代码时会自动缩进,把代码搞得一团糟糕,甚至可能因为某行的一个注释造成后面的代码全部被注释掉,我知道有同学这个时候会用vi去打开文件再粘贴上去(鄙人以前就是这样),其实需要先设置一下 s...