OBServer进程初始化时会调用其init_multi_tenant方法完成多租户环境的初始化,即初始化ObServer类中的multi_tenant_属性(ObMultiTenant类的实例),它被用来表达OBServer进程中的多租户环境。
多租户环境的初始化分为两个阶段:
(1)调用multi_tenant_的init方法对多租户环境做第一阶段初始化
首先根据系统中可用的CPU核心数以及配置中的信息,计算出工作线程的初始数量:(可用的核心数+服务器租户的虚拟核心数)×默认每核心线程数+为系统级租户预留的线程数。
如果是运行在Mini模式,工作线程的初始数量还会被减半。
空闲线程数设置为初始的工作线程数。
工作线程的最大数量:在初始数量的基础上加上可用CPU核心数的16倍,在这个数量和硬上限4096(宏定义OB_MAX_THREAD_NUM)之间取较小值,然后再与初始数量取较大值。
用初始工作线程数、空闲工作线程数、最大工作线程数初始化工作线程池(ObWorkerPool类实例)。如图3.4所示,工作线程池的核心实际上是一个名为workers_的队列,线程池的初始化过程就是创建出很多个ObThWorker实例并且将它们推入到workers_队列中。每一个ObThWorker都会形成一个线程,初始时这些线程都不服务于任何租户,当多租户环境开始运转(执行multi_tenant的start方法)后,多租户环境的守护线程MultiTenant将会为各个租户从线程池中取得所需的线程,届时工作线程才会与租户关联起来。
图3.4 工作线程池结构
(2)在多租户环境中加入系统级的租户
从OceanBase外部来看,集群中仅有一个系统级别的租户sys,其他的租户都属于为用户创建的普通租户。事实上,在OceanBase内部,存在着sys、gts、monitor等多个用于内部机制的系统级租户。
初始化完成后,当多租户环境进入到运行阶段时会产生一个专用于多租户环境的守护线程,其名称会被设置为“MultiTenant”。在MultiTenant的主函数(ObMultiTenant::run1())中,每隔10s会对租户列表进行一次遍历,为每个租户调用其timeup方法。在租户的timeup方法中,会针对其拥有的工作线程数量进行检查,如果发现数量不足,则会尝试从工作线程池中为该租户取得足够的工作线程(将ObThWorker的tenant_属性设置为该租户) 。一旦工作线程与某个租户相关联,其线程名称会被设置为“TNT_L #_#”,其中第一个#代表该线程处理的请求的层次号,第二个#代表租户的数字ID。