情景复现
在使用 Docker 部署 Seata 时遇到了一些问题:
我想尝试一下使用 Docker 部署一套包含 Nacos、Seata 和 Sentinel 的高可用微服务框架,既然部署了 Nacos ,那肯定是要将 Seata 也交给 Nacos 管理,并由 Nacos 管理 Seata 的数据库配置(使用 Nacos 的配置管理功能)。
首先我安装官方文档的高可用示例创建了 Data Id:seataServer.properties , Group:SEATA_GROUP 的配置项,但是并没有使用示例中所写的 Properties 的配置方式,而是使用 Yaml 的方式,这在我首次启动之后直接导致了无法读取 store 配置项,而是直接走了默认的 file,从日志中也可以轻易看出:
11:11:58.362 INFO --- [ main] [rver.lock.LockerManagerFactory] [ init] [] : use lock store mode: file
11:11:58.424 INFO --- [ main] [a.server.session.SessionHolder] [ init] [] : use session store mode: fileShellSession可以看到两者对应的 store mode 都为 file ,而不是我们在配置中写的 db。然后确定了发生这个问题的根本原因就是在 Nacos 的配置文件中使用的了 Yaml,将其改为 Properties 格式就好了:
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://ip:3306/seata?useUnicode=true
store.db.user=root
store.db.password=${YourPassword}ShellSession重新启动我们就会遇上第二个问题:启动时报错,大意是在 /lib/jdbc目录下没有找到 mysql 驱动,经过了解是由于 Seata 适配了多种数据库,因此并没有帮我安装数据库驱动依赖,需要我们手动导入,我这里使用的方法是先以 store.mode=file 的方式启动应用,然后进入到容器中,将提前准备好的 mysql-connector-java.jar放到了lib/jdbc 和seata-server/lib/jdbc这两个文件夹下了,多了一个seata-server/lib/jdbc是因为 gpt 提醒我 seata 的应用程序依赖很有可能在这个文件夹下,因此我两个都试了试,然而重新启动后程序依然报错,这时 gemini 提醒我:我可以在 seata-server 这个包下找一找有没有一个文件夹存放大量的 jar 包,果然存在一个 libs 包,里面直接存放了大量的 jar 包,于是我在 libs 下创建 jdbc 文件夹,并将依赖放置其中,依然报错,最后我删除 libs 文件夹,直接将其放入 libs 中,程序启动成功!
事后总结
后来想想,确实是在实践过程中压根没有动脑,明知道 seata-server 是一个正常的 SpringBoot 应用,还看到了日志说他缺少了一个依赖,那肯定是将缺少的依赖存放到放置项目依赖的地方就可以, Mysql 驱动也不只是众多依赖中的一个,唯一不同的是他没有被官方预先放置而已,他不应该具有特殊性的呀!
但是还有一个问题:为什么必须直接放置在 libs 下,就连再创建一个子目录也不行呢?经过 gemini 解答,目前的理解如下:
首先 JVM 是从 Classpath 中去寻找 jar 包的,也就是我如果我们想要 JVM 找到 Mysql 驱动,就需要将他写入到 Classpath 中,而他的构建是由启动脚本来完成的(经过查看seata-sever 包下确实有 seata-setup.sh),启动脚本中会定义 Classpath 的路径构建规则,但是一般他不会对文件夹进行递归操作,所以 JVM 只能看到 libs 下的文件,而看不到他的子文件中的内容。
Comments NOTHING