ATS插件开发基础
转载自 https://blog.zymlinux.net/index.php/archives/540
ATS插件开发需要提前了解ATS的插件的一些设计思想,以及系统提供的一些不同方向。我们将会介绍ATS的基础开发知识,以利于后续的插件开发课程讲解。
ATS的SDK文档,是了解ATS的核心设计、接口设计的很重要资料,甚至是老的PDF版本文档,都是非常非常有用的资料。以至于我经常建议完全不了解ATS核心代码的初学者也好好看看SDK文档,这里讲的很多基础知识,有利于对核心的深入理解。ATS的API以及核心插件接口设计是一个很庞大的工程,其设计思想我们很难一下消化掉,这里点出一些知识点供大家参考。如有纰漏、谬误之处,以SDK文档、代码注释、代码为准。
官方SDK文档
历史的SDK PDF文件
下一篇:手把手教你写plugin
ATS开发环境
名词解释
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<proxymutex> mutex;LINK(Continuation, link);int handleEvent(int event = CONTINUATION_EVENT_NONE, void *data = 0) {return (this->*handler) (event, data);}Continuation(ProxyMutex * amutex = NULL); };
Continuation主要包含:
- handler:当前的Continuation处理函数。
- mutex:Continuation的锁。
- link:链接到其他Continuation的双链表。
- handleEvent:接收event的代码和数据,并交给当前的处理函数处理。
结构非常精炼,并不代表特殊含义。
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</proxymutex><proxymutex> 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,有几个需要注意的地方:
- Action是可以再入的
- 撤销必须是由任务的callback处理机来做
- 要撤销必须先拿到锁
- Action是由处理机创建的,在完成或撤销的时候,也是由处理机负责的。状态机不能在Action完成或撤销后再访问它
Event
Event是由Event处理机返回的一种Action。是可以用来调度出去从而异步处理的任务(Action)。event是不可再入的。由于它继承自Action,因此也具有可以撤销的机制,同时更可以在收到Event后处理或不处理而再调度出去,这个很乱啊:D
Event的调度分为4种:
- _imm:立即执行,这个模式讲会直接让Event进入待执行队列
- _at:在未来某个具体时间,指定具体事件执行
- _in:在未来某段时间后,指定具体多久之后执行
_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结构,有如下几点需要注意:
- 状态机只能在那个call-back线程中,发起调度,并且需要拿到continuation的锁。
- 撤销机制与Action类似,也需要在call-back状态机拿到锁的情况下做。
- 状态机中,Event事件的代码是需要全局统一的
VC
VConnection是ATS核心、插件都常用的一种面向stream的数据抽象结构。主要可以理解为一个数据读写管道,在某些场景下,有点类似FD的效果。VConnection继承自continuation,也是会call-back到处理机处理的。这个基类是封装上层通信管道的基础。
VConnection提供关键的几个接口:
- do_io_read
- do_io_write
- do_io_close
- do_io_shutdown
- reenable 用来通知另一端可以实施下一步动作
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文件,默认并没有提供给大家
- InkAPIHughes.h 为Hughes设计的Prefetch API,用到Prefetch功能的可以看看。
- InkAPIPrivateIOCore.h 很底层的API,如锁、Buffer、网络包等,应该没有需要用到的必要。
C++ API
LinkIn 公司为ATS添加了一套C++的API,需要在编译的时候加
--with-cpp11api
选项configure才行。C++ API包含:
- ts-cpp11.h
- ts-cpp11-headers.h
这个API可能不够完备
ATS插件环境
ATS 插件模式
- global:这种模式的插件,是会对全局有效,可以有效拦截整个流程,包括客户端建连过程。
- remap:在用户请求经过remap完成后的阶段hook进去,是一个添加网站应用逻辑的地方。
ATS 插件模板
- global
- TBD 我希望能够用
tsxs
这个工具能够生成一些模板代码,正在整理中
- TBD 我希望能够用
- remap
- TBD
- global
ATS核心流程
- 流程
- hook点
关于状态机
主HttpSM
HttpSM是指ATS的核心http流程状态机,即proxy/http/HttpSM.cc(.h)中定义的状态机,这是整个proxy业务的大状态机,所有的其他流程都是依附于(或关联于)这个状态机上的。如回源、读写cache等。当然这个文件也是目前ATS中最大的2个文件之一,以近万行的代码挑战你的能力。
HttpSM相对插件开发者来说,几乎是不可见的,因为所有的插件都是hook到整个http流程中间来的。只有想看核心代码的同学才有意义。
子状态机
所谓子状态机,其实在ATS的事件系统里,到处都是,只要是做一个稍微复杂点的异步处理必然要引入一个状态机(processor)来做,相对来说这些都比较微型化。
ATS的主HttpSM状态机并不是完全不可控制的,ATS允许你很大程度的自己定制自己的状态机,甚至绕过绝大多数HttpSM流程,这里可以参考的代码有:
- Prefetch:proxy/Prefetch.cc(.h),这是一个做到核心中的transform插件,在用户访问html的时候,解析html并提取所有页面元素,主动发起回源以预取,提高用户感受。这里的核心是一个后台回源状态机,典型的设计可以参考。
- example/protocol,这是一个完全脱离HttpSM的协议代码例子,这里定义了一个protocol插件,直接accept并且自己建立了自己的SM状态机,走自己的独立流程(TxnSM.c)。
ATS代码树
iocore
IOcore系统是定义最核心的ATS基础模块,定义了底层的所有关键框架,这些模块和框架与业务系统相对独立,其中包括:
- eventsystem 事件系统,定义了事件系统的调度机制、buffer管理系统等等
- net 网络层,定义了网络处理的基础框架
- aio 异步IO的实现,实现了类似于libc的AIO线程方案
- cache 缓存与文件系统,管理磁盘存储、内存cache等
- cluster 集群通信系统,解决集群数据交互协议RPC
- dns DNS解析代码,我们需要在异步环境下做DNS的解析客户端
- hostdb DNS缓存系统,解决了DNS的中间cache
IOcore系统,代码逻辑相对隔离的还是不错的,因此各个模块是能够比较独立的理解和学习的。
proxy
Proxy模块可以说是ATS的业务逻辑,也是traffic_server的主代码所在地。
Proxy下有几个比较关键的模块:
- logging:所谓的access日志模块
- api:我们所说的API都是定义在这里的。(C++API放在lib目录下)
- config:ATS的配置文件源文件目录
- http:这是关键的状态机目录
其他各种功能,都放在proxy/目录下,这里也是功能最多、最乱的一滩子啦。
cop
cop是用来存放traffic_cop代码的,相对来说是最简单的代码啦。
mgmt
这里存放的是traffic_manager代码。其中仍有许多需要清理的老代码残渣。
lib
这里存放的是ATS的基础库,继承自原Inktomi++的仿C++标准库,ATS对外部库依赖比较少皆因这个库成型比较早,并且覆盖面比较全面。某人说这个就是C++标准库啊。话说当年(95-99年)ATS开发的时候,C++标准还在娘胎中吧?
lib下有几个关键模块:
- ts:即所说的ATS C++标准库
- records:这个目录是stats|records系统的关键
example
存放SDK介绍的,以及未介绍的所有插件参考代码。可以放心的说,ATS能够做的场景,在这个目录下都可以找到比较接近的例子。从这里的代码开始业务编程是很好的选择。
tools
存放性能测试工具如http_load jtest工具以及状态跟踪工具tstop等
plugins
存放所有公开到主代码的插件系统代码:
- esi
- cacheurl
- regex_remap
- 其他experimental插件
doc
存放Admin手册、man手册等
rc
init脚本等
相关文章:

NET基础(3):is 和 as 操作符
在C#语言中进行类型转换的另外一种方式是使用is和as操作符。is检查对象是否兼容于指定类型,返回Boolean值true或false。注意,is操作符永远不抛出异常,例如以下代码: Object o new Object();Boolean b1 (o is Object); //返回…

制作大白菜PE盘
大白菜是一款功能非常强大的U盘启动盘制作工具,通过大白菜我们可以把U盘做成可以引导电脑启动的启动盘,同时可以用于装系统或维护系统,虽然制作方法非常简单,不过还是有很多人不懂如何制作大白菜U盘启动盘,这两天我刚好…
为方便ATS管理建立的一些命令别名
转载自https://blog.zymlinux.net/index.php/archives/129 玩ats经常需要切换目录什么感觉敲得麻烦了就建立了一些命令别名,就方便多了。 在用户目录下的.bashrc文件中加入以下内容: alias alogcd /usr/local/var/log/trafficserver;pwd alias atscd /us…

short s1 = 1; s1 = s1 + 1;有错而short s1 = 1; s1 += 1正确
这个问题以前碰到过,也研究过,发表一下: 如果你认为表达式(x i)只是表达式(x x i)的简写方式,这并不准确。这两个表达式都被称为赋值表达式。第二个表达式使用的是简单赋值操作…

pom文件中引入常用的maven仓库
给大家分享几个maven仓库,如果本地总是下载很慢的话可以尝试换一下仓库或者多加几个。可以直接拖放在pom.xml中使用。 阿里云仓库 <mirrors><mirror><id>alimaven</id><name>aliyun maven</name><url>http://maven.ali…

ats新手学习参考
转载自https://blog.zymlinux.net/index.php/archives/129 首先申明本人是个实实在在的菜鸟,现在也只是搭建起来ats玩玩简单的,写本文只是为了给完全的小白一个参考而已。 本人刚开始接触ats的时候,从ats安装到配置也遇到了很多基本的问题&am…

[svc]磁盘接口与RAID
一 磁盘接口 IDE 传统家用: /dev/hda1 SISC 传统服务器: /dev/sdb1 SATA 现在家用 SAS 现在服务器用 FC(光纤通道) 高级服务器 注意: 分区编号,1-4只能给主分区或扩展分区使用,逻辑分区是基于扩展分区来搞的,编号从5开始. MBR分区参考 现在计算机性能瓶颈往往在硬盘: …

条形码?二维码?生成、解析都在这里!
二维码生成与解析 一、生成二维码 二、解析二维码 三、生成一维码 四、全部的代码 五、pom依赖 直接上代码: 一、生成二维码 public class demo {private static final String path1"D:\\code.jpg";private static void qr(String text,int width,int w…

异步预热在线视频实现
转载自https://blog.zymlinux.net/index.php/archives/100 毕业之际给学校搭建了基于ATS的正向代理缓存服务器,专门用来处理优酷土豆等在线视频流量。通过改写一个浏览器做成在线视频专用浏览器,内置了ATS的代理设置。 用php配合memcacheq和小脚本实现了…

文本输入框、密码输入框
当用户要在表单中键入字母、数字等内容时,就会用到文本输入框。文本框也可以转化为密码输入框。 语法: <form><input type"text/password" name"名称" value"文本" /> </form> 1、type: 当t…

Linux安装mysql,一步到位!
今天在腾讯云上面买了一个服务器,想要把自己的项目部署一下,就要安装mysql,以下是我的安装步骤,在网上有很多人把install敲错了,还有的少-get,种种错误试完之后,我决定发一篇 sudo apt-get install mysql-…

Ubuntu 12.04安装firefox 26中的flash plugin方法
Ubuntu 12.04 64bit中安装firefox 26中的flash player插件的方法昨天, 有最新的firefox 26更新了,可是我在软件更新中无法下载到ubuntu官方源中的flash plugin,详细的情况可以参见如下网页,这个问题我一年前也遇到过,特记录下来,以备后来查阅.http://blog.sina.com.cn/s/blog_9…

内联式css样式,直接写在现有的HTML标签中
CSS样式可以写在哪些地方呢?从CSS 样式代码插入的形式来看基本可以分为以下3种:内联式、嵌入式和外部式三种。这一小节先来讲解内联式。 内联式css样式表就是把css代码直接写在现有的HTML标签中,如下面代码: <p style"col…

Linux下安装Java8
Linux(ubuntu)下Java8安装 1.下载jdk8 这个看大家了,linux版本的就可以 2.创建jvm文件夹 在根目录下创建名为jvm的文件夹(在哪里创建看个人) $ sudo mkdir jvm3.将下载的包解压到jvm文件夹下 $ sudo tar zxvf 压缩包路径/名字 -C /jvm…

RTMFP协议
RTMFP是Adobe公司开发的一套新的通信协议,该协议可以让使用Adobe Flash Player的终端用户之间进行直接通信。用Adobe AIR框架开发的程序也可以用此协议来发布直播、实时信息。 通过使用RTMFP, 那些原来直播、实时通信的应用,比如社区、音视频聊天和多人…

CodeForces 595A
题目链接: http://codeforces.com/problemset/problem/595/A 题意: 一栋楼,有n层,每层有m户,每户有2个窗户,问这栋楼还有多少户没有睡觉(只要一个窗户灯亮就代表这户没有睡觉&#x…

将Eclipse中Web项目打成war包
将Eclipse中Web项目打成war包 请按如下操作即可:

测试代码发布到博客效果(Windows Live Writer发布)
测试代码发布到博客效果(Windows Live Writer发布) public class SwitchCase {/*** 1、switch后面的表达式为常量表达式,类型只能是可以转化为int、enum(1.6)、String(1.7)的类型* 2、可以转化为int类型的数据类型有:byte、short、int、char* 3、boolean类型的数据类…

设置腾讯云linux服务器中 MySQL 允许远程访问
申请了一台linux腾讯云服务器,想要把数据库搭建在上面,本地的Windows直接可以访问 以下就是具体的操作流程,首先你需要安装好一个mysql,安装方法–>mysql安装(Linux) 接着就开始操作咯: 一、开启 MySQL 远程访问权…

js 判断js,css是否引入,确保不重复引入
js 判断js,css是否引入,确保不重复引入 (2009-10-31 21:33:44) 转载▼标签: 杂谈 分类: js基本原理:function loadjscssfile(filename, filetype){if (filetype"js"){ //if filename is a external JavaScript filev…

Ubuntu18彻底删除MySQL5.7数据库
首先在终端中查看MySQL的依赖项:dpkg --list|grep mysql (有或者没有都可以继续执行) 移除所有mysql公共依赖:sudo apt-get remove mysql-common 卸载:sudo apt-get autoremove --purge mysql-server-5.7 清除残留数据:dpkg -…

软件缺陷处理流程
今天,我们的主任研究了一下我出的软件缺陷处理流程,觉得不严谨,他重新梳理了一个,偶还是觉得自己梳理的比较直接,没有那么复杂。 这里博客记录,用于纪念我的心血,因为说不定哪天偶的这点心血会被…

Linux下tomcat的安装与卸载以及配置(超简单)
无敌简单的几步 1、安装 //首先你需要下载好tomcat包 sudo tar -xvzf apache-tomcat-7.0.85.tar.gz(这里是包名) -C 你要放的位置2、卸载 rm -rf 你的tomcat目录3配置: 进入目录/tomcat/apache-tomcat-8.5.51/bin,编辑文件startup.sh,在…

《创业维艰分享之五》所有得,有所乐,日事日清,循序渐进。
这两个月公司连续做了两个大客户紧接着发布新版本再然后又是连续五个小版本迭代计划。 每天16小时的超强度工作,我已经看到兄弟的脸上都写着一个字:累! 我自己又何尝不是,既是客服,又是程序员,还必须是行政…

docker上你必须会的那些命令
一、基础类 查看docker信息 # 查看docker版本 docker version # 显示docker系统的信息 docker info # 日志信息 docker logs # 故障检查 service docker status # 启动关闭docker sudo service docker start|stop二、容器操作命令 1、创建删除容器 # 创建一个容器命名为 te…

iOS开发UI篇—transframe属性(形变)
iOS开发UI篇—transframe属性(形变) 1. transform属性 在OC中,通过transform属性可以修改对象的平移、缩放比例和旋转角度 常用的创建transform结构体方法分两大类 (1) 创建“基于控件初始位置”的形变 CGAffineTransf…

docker一步安装mysql,docker的魅力就在于此
正常来说,使用docker安装东西的步骤是serach它有没有,然后pull它 这里其实只要一步(如果你没有安装过、没有端口占用等问题的话!!) $ docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORDroo…

python-day05正则表达式
相关参考文档地址:http://bbs.fishc.com/thread-57073-1-1.html(小甲鱼论坛) 摘录老师之精华 re模块用于对python的正则表达式的操作。 字符: . 匹配除换行符以外的任意字符 \w 匹配字母或数字或下划线或汉字 \s 匹配任意的空白符 \…

Vim编辑器的常用快捷键.
Linux中的文本操作离不开Vim编辑器的使用. Vim编辑器的使用相对门槛较高.需要挺长一段时间的适应. 总结一些Vim使用过程中常用的命令(这些命令基本上都是在vim的命令模式下使用) 1.跳转到文本的开头gg 2.跳转到文本的末尾G (shiftg) 3.查看文本的总共有多少行(:set nu) 关于这个…

在docker上安装部署tomcat项目 超简单,拿来主义
在docker中部署tomcat,非常简单,而且省去了手动安装jdk等步骤,只需要将war包复制在容器tomcat实例中的webapps下面即可。以下将详细讲解流程: 在windows中打好包以后用winSPC拖放到linux系统中,我的直接放在了/home/ub…