Oracle JDBC:如何禁用高CPU消耗的安全特性?
Oracle JDBC驱动在连接创建/认证阶段会执行一些高CPU消耗的调用,例如使用SecureRandom(即便已采用/dev/urandom)或AES加密算法。
以下是高开销操作的栈追踪片段示例:
javax.crypto.Cipher.doFinal(byte[], int, int, byte[]) line: 2325 oracle.net.aso.e.b(byte[], int, int, byte[]) line: not available oracle.net.aso.ac.f(byte[]) line: not available oracle.net.aso.c.f(byte[]) line: not available oracle.security.o5logon.O5Logon.a(byte[], java.lang.String, java.lang.String) line: not available oracle.security.o5logon.O5Logon.generateOAuthResponse(int, byte[], java.lang.String, java.lang.String, java.lang.String, byte[], byte[], byte[], byte[], byte[], byte[], int[], int[], boolean, byte, byte[], int, int, byte[], int[]) line: not available oracle.security.o5logon.O5Logon.generateOAuthResponse(int, byte[], java.lang.String, java.lang.String, byte[], byte[], byte[], byte[], int[], boolean, byte, byte[], int, int, byte[], int[]) line: not available oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(java.lang.String, java.lang.String, java.lang.String, long, int, int, byte[][]) line: 1179 oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(java.lang.String, java.lang.String, java.lang.String, long) line: 1025 oracle.jdbc.driver.T4CConnection.logon(org.ietf.jgss.GSSCredential) line: 743 oracle.jdbc.driver.T4CConnection(oracle.jdbc.driver.PhysicalConnection).connect(org.ietf.jgss.GSSCredential) line: 793 oracle.jdbc.driver.T4CDriverExtension.getConnection(java.lang.String, java.util.Properties, org.ietf.jgss.GSSCredential) line: 57 oracle.jdbc.OracleDriver(oracle.jdbc.driver.OracleDriver).connect(java.lang.String, java.util.Properties, org.ietf.jgss.GSSCredential) line: 747 oracle.jdbc.OracleDriver(oracle.jdbc.driver.OracleDriver).connect(java.lang.String, java.util.Properties) line: 562 [...]
这类操作在生产环境和常规测试环境中并无问题,但在本地测试数据库的自动化测试场景中会带来不必要的CPU开销与延迟。
技术问询
是否存在方法可禁用部分或全部此类高开销安全特性?例如通过降低或禁用JDBC驱动的认证机制,或其他措施来减少CPU耗时?
补充说明
- 使用本地自建数据库,配置基本默认,采用普通用户名/密码认证,JDBC驱动版本为19.3。
- 场景中有大量短生命周期应用,每个应用创建1-2个连接,执行几秒任务后就终止,连接池无法解决该问题。
- 性能分析显示:在仅循环创建和关闭JDBC连接的测试中,23%的耗时被Oracle JDBC驱动调用的
javax.crypto.SecretKeyFactory.generateSecret()占用。
可行的优化方案
针对你的测试场景,以下几种方法可以有效降低连接认证阶段的CPU开销:
1. 禁用Oracle高级安全选项(ASO)
Oracle JDBC驱动默认启用了加密和校验等高级安全特性,你可以通过JDBC URL参数强制禁用:
jdbc:oracle:thin:@//localhost:1521/ORCL?oracle.net.encryption_client=REJECT&oracle.net.crypto_checksum_client=REJECT
也可以通过Java系统属性全局设置:
System.setProperty("oracle.net.encryption_client", "REJECT"); System.setProperty("oracle.net.crypto_checksum_client", "REJECT");
该配置会直接跳过AES加密相关的高CPU操作,是最直接有效的优化手段。
2. 切换到轻量版认证协议
Oracle 19c驱动默认使用O5Logon协议,你可以强制切换到更轻量的O3Logon协议,通过JDBC URL添加参数:
jdbc:oracle:thin:@//localhost:1521/ORCL?oracle.jdbc.useO3Logon=true
注意:该协议安全性较低,仅建议在测试环境使用。
3. 优化SecureRandom性能
即便已使用/dev/urandom,可以通过以下系统属性确保JVM使用非阻塞随机源:
System.setProperty("java.security.egd", "file:/dev/./urandom");
路径中的./用于绕过JVM对/dev/urandom的特殊缓存处理,进一步降低随机数生成的CPU开销。
4. 修改测试数据库端配置
如果是本地测试数据库,可修改sqlnet.ora文件,禁用服务器端的加密和校验要求:
SQLNET.ENCRYPTION_SERVER = REJECT SQLNET.CRYPTO_CHECKSUM_SERVER = REJECT
客户端驱动会自动匹配服务器配置,跳过安全相关的高开销操作。
效果验证
应用上述配置后,重新运行连接测试,javax.crypto.SecretKeyFactory.generateSecret()和Cipher.doFinal()这类高CPU调用的占比会显著下降,连接创建延迟也会明显降低。
内容的提问来源于stack exchange,提问作者MRalwasser

