参数“Disconnect Application Module Upon Release”的实验报告

通过实验对比分析AMPool中DisconnectApplicationModuleUponRelease等参数对数据库连接消耗的影响,提出了针对不同应用场景的参数配置建议。
用AM Pool时,发现数据库连接消耗的特别快。用户每次访问一个页面,都会新占用一个数据库连接,这显然让人无法接受。
查看了有关AM Pool的设置文档,发现参数“Disconnect Application Module Upon Release”与释放数据库连接有很大关系。

参数Disconnect Application Module Upon Release含义
强制AM 实例每次释放回池中时,同时释放掉其对应的JDBC 连接。默认为false,不选中。
好处是每次AM实例不用再从数据库连接池拿连接,而且连prepared statements也可以直接拿来就用。

为了进一步搞清楚问题所在,获得最佳性能,我做了如下实验:
为了最准确的监控数据库连接数,使用如下SQL语句:
conn sys/welcome1 as sysdba;
select count(sid),username from v$session group by username;

实验1. 全部使用默认值

现象:每访问一次页面,数据库连接都增加一个。手工测试了10次,数据库连接增加到了11个。
解释:用户每访问一次页面,都会从AM Pool中获取一个实例,使用完毕后(即Request请求结束后),AM实例会释放回Pool中,但该AM实例所关联的数据库连接并没有释放(方便下次直接使用,不用再从数据库池中获取)。
由于数据库连接池默认很高:4096,所以在达到这个数字前,数据库连接会持续增加。


实验2. 选中Disconnect Application Module Upon Release,其它设置默认。

现象:每访问一次页面,数据库连接都增加一个。手工测试了10次,数据库连接始终为2个。
解释:用户每访问一次页面,都会从AM Pool中获取一个实例,使用完毕后(即Request请求结束后),AM实例会释放回Pool中,同时强制释放该AM实例所关联的数据库。
不好的地方是下次需要数据连接时,需要重新从数据库池中获取。


实验3. 改动参数设置见下图,其它设置默认。

Idle Instance Timeout:设置为1分钟
Pool Polling Interval:设置为30秒
Maximum Instance Time to Live:设置为2分钟。

现象:开始时每访问一次页面,数据库连接都增加一个。手工持续测试了10次,占用数据库连接数达到12个。
经过大约5分钟后,再次手工测试了10次,所占用数据库连接数依然保持达到12个。
这个和我想象的有出入,我以为经过5分钟后,所有的数据库连接都应该释放了,难道是因为AM Pool的最大值太大了,所以总要保留一些AM实例备用?
那我减少AM Pool的最大值,是不是就会把多余的AM实例释放了? 实验4将验证这一猜想。
解释:AM实例不活动时间超过1分钟后,将被标记为“可以清除”,并在30秒后被清除。
值得注意的是,即使AM实例被清除了,它依然关联着一个数据库连接,直到超过了AM的最大生存时间:2分钟后,才释放其所关联的数据库连接。

实验4. 改动了一些有关AM Pool Size的参数,见下图,其它设置与实验3一样。


现象:开始时每访问一次页面,数据库连接都增加一个。手工持续测试了10次,占用数据库连接数最高达到5个。继续测试,仍然是5个。
解释:至于为何是数字5,经多次实验,发现其实与Maximum Available Size参数值无关,这应该是AM Pool优化算法的自然结果。
用5个数据库连接就可以为多个用户提供访问,这才是我们期待的结果。

经过以上实验,结论如下:
(1)Disconnect Application Module Upon Release 参数默认不选中是有利于性能优化的。
(2)参数Idle Instance Timeout、Pool Polling Interval、Maximum Instance Time to Live 应该配合使用。
基本原则是:Maximum Instance Time to Live >Idle Instance Timeout + Pool Polling Interval(否则还没等AM Pool标记清除之前,AM实例就已经被清除了)。
至于何种组合为最优,需要做性能测试之后,比较之后得出。
(3)每个AM 池的设置可以根据自身情况有所不同。
如果AM的调用时间比较长,可以适当增大Maximum Instance Time to Live;Maximum Pool Size 基本接近或略高于用户并发数的峰值;
如果用户并发数很高,可以适当减小Maximum Instance Time to Live,便于回收AM 实例和数据库连接;
对于操作频繁,但事务较小的AM,可以适当增大Idle Instance Timeout、Pool Polling Interval,尽量直接重用AM实例,无需重新获取。
(4)ADF自带的数据库连接池一般不用于生产环境。在生产环境下,应该使用JDBC Datasource的方式,使用WLS的数据库连接池来管理。基本原则是数据库连接池的最大值=AM Maximum Pool Size。

实验说明
本测试是手工测试,参数值的设定仅用于考证Disconnect Application Module Upon Release及相关参数的含义,不能作为生产环境下的参数设置的依据。
生产环境下的参数设置应该做完一系列的性能测试后,逐步调优各项参数,比较之后得出。
本来想用Oracle Application Test Suite 来做压力测试,但安装使用后,发现我的机器根本承受压力测试,呵呵。

参考文献:
1. http://andrejusb.blogspot.com/2010/02/optimizing-oracle-adf-application-pool.html 

转自马云博客maping930883.blogspot.com/2011/09/adf109adf-disconnect-application-module.html

`pa_context_load_module()` 是 PulseAudio 提供的用于**从客户端加载服务端模块**的函数,常用于动态扩展 PulseAudio 功能(如加载虚拟设备、回环模块等)。 --- ### 📌 函数原型(来自 `pulse/context.h`) ```c pa_operation* pa_context_load_module( pa_context *c, const char *name, const char *argument, pa_context_index_cb_t callback, void *userdata ); ``` --- ### 🧩 参数详解 | 参数名 | 类型 | 说明 | |--------|------|------| | `c` | `pa_context*` | 已连接到 PulseAudio 服务端的上下文对象 | | `name` | `const char*` | 要加载的模块名称(如 `"module-null-sink"`) | | `argument` | `const char*` | 传递给模块的参数字符串(可为 `NULL`) | | `callback` | `pa_context_index_cb_t` | 模块加载成功后的回函数(可为 `NULL`) | | `userdata` | `void*` | 用户自定义数据,回时传回(可为 `NULL`) | --- ### 📌 参数详细说明 #### 1. `pa_context *c` - 一个已经连接成功的 PulseAudio 上下文。 - 必须用 `pa_context_connect()` 成功连接后才能使用。 #### 2. `const char *name` - 要加载的模块名称。 - 模块通常位于 `/usr/lib/pulse-<version>/modules/` 目录下。 - 示例模块: - `module-null-sink`(虚拟输出设备) - `module-loopback`(音频回环) - `module-alsa-sink` / `module-alsa-source`(硬件输入输出) - `module-echo-cancel`(回声消除) #### 3. `const char *argument` - 向模块传递的参数字符串,格式为 `"key1=value1 key2=value2"`。 - 不同模块支持的参数不同,详见模块文档。 - 示例参数: ```bash "sink_name=my_sink rate=48000 channels=2" ``` #### 4. `pa_context_index_cb_t callback` - 类型定义为: ```c typedef void (*pa_context_index_cb_t)(pa_context *c, uint32_t index, void *userdata); ``` - 当模块加载完成后,PulseAudio 会用此回函数。 - `index` 表示加载成功的模块的 ID(用于后续卸载等操作)。 - 如果不需要回,可以设为 `NULL`。 #### 5. `void *userdata` - 用户自定义数据,回函数中会原样传回。 - 通常用于在回中恢复上下文信息或状态。 --- ### 🧪 示例代码(加载 `module-null-sink`) ```c #include <pulse/context.h> #include <pulse/mainloop.h> #include <pulse/module.h> void module_load_callback(pa_context *c, uint32_t index, void *userdata) { printf("模块加载成功,模块ID: %u\n", index); } int main() { pa_mainloop *mainloop = pa_mainloop_new(); pa_mainloop_api *mainloop_api = pa_mainloop_get_api(mainloop); pa_context *context = pa_context_new(mainloop_api, "ModuleLoader"); pa_context_connect(context, NULL, PA_CONTEXT_NOFLAGS, NULL); while (pa_context_get_state(context) != PA_CONTEXT_READY) { pa_mainloop_iterate(mainloop, 1, NULL); } // 加载模块:创建一个名为 my_sink 的虚拟输出设备 pa_operation *op = pa_context_load_module( context, "module-null-sink", "sink_name=my_sink", module_load_callback, NULL ); // 等待操作完成 while (pa_operation_get_state(op) == PA_OPERATION_RUNNING) { pa_mainloop_iterate(mainloop, 1, NULL); } pa_operation_unref(op); pa_context_disconnect(context); pa_context_unref(context); pa_mainloop_free(mainloop); return 0; } ``` --- ### ✅ 总结 | 参数 | 是否必须 | 说明 | |------|----------|------| | `c` | ✅ 是 | 已连接的上下文 | | `name` | ✅ 是 | 模块名称 | | `argument` | ❌ 否 | 模块参数字符串 | | `callback` | ❌ 否 | 加载完成后的回函数 | | `userdata` | ❌ 否 | 用户自定义数据 | --- ### 🔁 模块卸载方法 使用 `pa_context_unload_module()` 卸载模块: ```c pa_context_unload_module(context, module_index, NULL, NULL); ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值