Docker部署对接MSSQL的Keycloak报RejectedExecutionException
故障根因
Legacy版本(17及更早版本,基于WildFly/JBoss架构)Keycloak启动阶段在Undertow子系统加载时抛出java.util.concurrent.RejectedExecutionException,和admin用户重复添加问题没有关联,日志中提示的admin用户已添加至/opt/jboss/keycloak/standalone/configuration/keycloak-add-user.json是启动流程早期的固定输出——只要启动流程走到用户初始化步骤就会打印该日志,和后续启动失败无因果关系。
该异常本质是JBoss启动线程池在Undertow子系统初始化完成前就进入关闭状态,触发任务拒绝,90%以上的场景由两类问题导致:
- 分配给Keycloak容器的内存配额不足,JVM频繁GC导致子系统加载超时,线程池提前触发关闭逻辑
- 对接外部MSSQL时JDBC驱动版本不兼容、网络连通性异常、账号权限不足,导致数据源初始化长时间阻塞,拖到启动超时触发线程池关闭
修复步骤
1. 先修正内存配置
Legacy版Keycloak没有内置容器内存感知逻辑,默认会按宿主机1/4内存分配JVM堆,如果docker服务配置的内存硬限制小于1G,大概率会触发启动超时。直接在docker-compose.yaml中显式指定JVM参数和内存限制即可:
services: keycloak: image: jboss/keycloak:16.1.1 # 替换为你实际使用的legacy版本号 environment: # 追加JVM内存参数,其余MSSQL对接、端口等原有配置保留 - JAVA_OPTS_APPEND=-Xms512m -Xmx1024m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m - DB_VENDOR=mssql - DB_ADDR=你的MSSQL地址 - DB_DATABASE=你的Keycloak库名 - DB_USER=你的数据库账号 - DB_PASSWORD=你的数据库密码 mem_limit: 1536m ports: - "8080:8080"
调整配置后执行docker-compose down -v 清理所有残留容器和匿名卷,再重新启动验证故障是否消失。
2. 排查MSSQL驱动与连通性问题
如果内存调整后故障依旧,优先排查数据源链路问题:
- 先拉取容器完整启动日志,搜索异常栈最底部的
Caused by块,如果存在SQLServerException、TLS handshake failure相关报错,就是MSSQL JDBC驱动版本不兼容导致的连接阻塞。 - Legacy版Keycloak自带的MSSQL驱动版本普遍低于8.x,对接SQL Server 2019及以上版本、或者强制开启TLS 1.2加密的MSSQL实例时必然出现连接hang住问题,需要自行构建镜像替换驱动:
新建Dockerfile:
同目录下新建module.xml:FROM jboss/keycloak:16.1.1 USER root # 清理旧版本驱动 RUN rm -rf /opt/jboss/keycloak/modules/system/layers/base/com/microsoft/sqlserver/main/* # 提前下载好10.2.x版本的JRE8兼容MSSQL驱动,和Dockerfile放在同目录 COPY mssql-jdbc-10.2.3.jre8.jar /opt/jboss/keycloak/modules/system/layers/base/com/microsoft/sqlserver/main/ # 新建对应module.xml配置文件,和Dockerfile放在同目录 COPY module.xml /opt/jboss/keycloak/modules/system/layers/base/com/microsoft/sqlserver/main/ RUN chown -R jboss:jboss /opt/jboss/keycloak/modules/system/layers/base/com/microsoft/sqlserver/ USER jboss
构建自定义镜像后替换docker-compose中的镜像地址即可。<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.3" name="com.microsoft.sqlserver"> <resources> <resource-root path="mssql-jdbc-10.2.3.jre8.jar"/> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> <module name="javax.xml.bind.api"/> </dependencies> </module> - 如果没有驱动相关报错,就在Keycloak所属的docker网络内启动一个临时MSSQL客户端容器,手动验证数据库地址、端口、账号密码、库名的连通性和读写权限,排除防火墙拦截、账号权限不足导致的连接阻塞问题。
内容的提问来源于stack exchange,提问作者user19238163
相关产品推荐
相关产品推荐

