对Linux平台OCI接口断网阻塞问题的处理

2019-01-30 08:05顾鹏程
电子技术与软件工程 2019年2期
关键词:线程调用队列

文/顾鹏程

1 引言

OCI是Oracle公司提供的Oracle数据库的C接口。一些监控系统,如轨道交通监控系统、电力调度系统等,需要在Linux平台对OCI进行封装。这类系统实时性要求较高,而OCI接口在Linux平台存在断网阻塞问题,这大大影响了系统实时性。本文提出一种对已封装Linux平台OCI接口的改进方法,可在接口断网阻塞时快速切换至备网。

2 OCI网络阻塞问题描述

长期不间断运行的系统不可避免会出现数据库服务器网线插拔或松动等问题,如果故障未及时恢复,OCI函数将长时间阻塞,例如在Ubuntu系统可能长达二十多分钟,这在大多数情况下是不允许的。监控系统一般配备主备网络,因此开发者往往希望当发生阻塞时,数据库接口能够自动切换网络。

3 阻塞问题处理

3.1 理论分析

在Linux系统中对于阻塞的解决通常使用sigalarm信号,指定信号触发时间,在可能的阻塞模块前调用alarm函数。经过实验,该方法只是对现有进程的打断,无法对接口函数给出错误返回值,且需退出进程,无法保证事务连贯。

还有采用线程和条件变量相结合的处理方法,将接口函数置于线程中执行,用条件变量计时等待接口函数返回。该方法不必退出程序,但未考虑主备网络切换,且条件变量方法存在弊端,即当信号先于等待发出时,信号将不再起作用,导致等待无法返回。

图1:任务流程

本文以上方法进行总结,提出一种结合泛型、线程、信号量方法的阻塞式任务线程方法,避免了上述方法的弊端,能够在接口阻塞时自动切换网络。

3.2 处理流程

首先在创建数据库连接时,创建一个任务线程,负责执行接口函数。接口函数通过泛型进入线程。当线程被获得任务时,触发“任务”信号以执行任务。当任务结束时,触发“返回”信号,主线程返回结果。调用接口函数的模块在获得“返回”信号前将一直阻塞并计时,当任务超时,采取tnsping的方式对网络状况进行判断,若网络未断将继续等待;若网络断开,将创建备用线程和备用网络数据库连接,而后执行阻塞任务,并退出原线程。具体流程如图1所示。

3.3 关键代码实现

本文采用VC10实现。泛型部分参考了任务队列的方法,增加了支持不同返回类型的修改。首先定义模版类class Base,结构体struct task_unit由class Base指针对象构造,表示任意函数任务。任务的产生由templatestatic task_unit gen(FUNCT func_, ARG1 arg1_...)实现。如果涉及引用类型参数,需要在函数中加入相应的引用符号。

阻塞任务队列部分采用ACE库实现,也可以选择Linux的C++标准库实现。线程类继承ACE_Task_Base,信号量采用ACE_Semaphore,“任务”信号初始化为 t_sem(0),“返回”信号初始化为r_sem(0)。线程通过调用t_sem.acquire()等待任务注入。主线程将任务注入任务线程后,调用t_sem.release()触发任务执行,调用r_sem.acquire(&timeout)等待任务完成,其中timeout为超时设置。任务结束时,线程调用ret_sem.release(),使主线程获得返回值。

4 结论

本文方法对Linux平台OCI接口的网络阻塞问题进行处理,针对已封装的接口函数,只需利用泛型、多线程、信号量,即可构造一个通用的阻塞模式任务队列,将接口函数置于阻塞任务队列下,在网络阻塞时,通关新的线程调用备用网络,解决了原本OCI接口函数长时间阻塞的问题。经过实验,该方法对旧有接口的改造工作量小,并且能实现应用的数据库连接在网络发生通断问题时进行自动切换。

猜你喜欢
线程调用队列
队列里的小秘密
核电项目物项调用管理的应用研究
在队列里
LabWindows/CVI下基于ActiveX技术的Excel调用
丰田加速驶入自动驾驶队列
浅谈linux多线程协作
基于系统调用的恶意软件检测技术研究
基于上下文定界的Fork/Join并行性的并发程序可达性分析*
利用RFC技术实现SAP系统接口通信
Linux线程实现技术研究