如何为每个请求设置一个数据库连接 Tomcat
How to set up Tomcat for one Database Connection per Request
我有一个部署在 Tomcat 服务器上的 Sparkjava 应用程序。它使用 SQL2O 与 MySQL 数据库进行交互。一段时间后,我开始无法连接到数据库。我试过直接从 SQL2O 连接、通过 HikariCP 连接和通过 JNDI 连接。在我开始获得 Communications link failure
之前,它们都工作了大约一天。这个应用程序最多一天被击中几次,所以性能完全不是问题。我想将应用程序配置为每个请求使用一个数据库连接。我该怎么做?
在我重新部署应用程序(再次覆盖 ROOT.war 之前)之后,该应用程序不会再次联机。重新启动 tomcat 或整个服务器什么都不做。
目前每个请求都会创建一个新的 Sql2o
对象并使用 withConnection
执行查询。如果我泄露了任何连接,我会感到非常惊讶。
这是一些示例代码(已简化)。
public class UserRepositry {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
protected Sql2o sql2o = new Sql2o("jdbc:mysql://mysql.server.name/dbname?serverTimezone=UTC", "username", "password");
public List<Users> getUsers() {
return sql2o.withConnection((c, o) -> {
return c.createQuery(
"SELECT\n" +
" id,\n" +
" name\n" +
"FROM users"
)
.executeAndFetch(User.class);
});
}
}
public class Main {
public static void main(String[] args) {
val gson = new Gson();
port(8080);
get("/users", (req, res) -> {
return new UserRepository().getUsers();
}, gson::toJson);
}
}
如果您依赖 Tomcat 为您提供连接:它来自一个池。如果您不喜欢,只需使用普通的旧 JDBC 并自己打开该连接(并确保也关闭它)。
对你的问题的回答就到此为止了。现在说说精神:来自池的连接没有错。在所有情况下,正确处理它是您的责任:访问连接并在完成连接后释放它 (close
)。连接来自池还是手动创建都没有区别。
如您所说,性能不是问题:请注意,创建连接可能需要一些时间,因此即使计算机大部分空闲,为每个请求创建一个新连接也可能对性能产生显着影响。您的服务器不会过热,但可能会增加一两秒的请求周转时间。
检查池的配置 - 例如validationQuery
(检测通信故障)或每个连接的使用限制。并确保您不会 运行 因为代码中的错误而陷入这些问题。无论如何,您都需要处理通信错误。而且,无论您是否使用池,处理都没有区别。
编辑:最后:您是否特别确定确实没有通信 link 失败?比如:每天晚上拔下数据库或路由器以连接真空吸尘器? (没有双关语意),防火墙 dropping/resetting 连接等?
我有一个部署在 Tomcat 服务器上的 Sparkjava 应用程序。它使用 SQL2O 与 MySQL 数据库进行交互。一段时间后,我开始无法连接到数据库。我试过直接从 SQL2O 连接、通过 HikariCP 连接和通过 JNDI 连接。在我开始获得 Communications link failure
之前,它们都工作了大约一天。这个应用程序最多一天被击中几次,所以性能完全不是问题。我想将应用程序配置为每个请求使用一个数据库连接。我该怎么做?
在我重新部署应用程序(再次覆盖 ROOT.war 之前)之后,该应用程序不会再次联机。重新启动 tomcat 或整个服务器什么都不做。
目前每个请求都会创建一个新的 Sql2o
对象并使用 withConnection
执行查询。如果我泄露了任何连接,我会感到非常惊讶。
这是一些示例代码(已简化)。
public class UserRepositry {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
protected Sql2o sql2o = new Sql2o("jdbc:mysql://mysql.server.name/dbname?serverTimezone=UTC", "username", "password");
public List<Users> getUsers() {
return sql2o.withConnection((c, o) -> {
return c.createQuery(
"SELECT\n" +
" id,\n" +
" name\n" +
"FROM users"
)
.executeAndFetch(User.class);
});
}
}
public class Main {
public static void main(String[] args) {
val gson = new Gson();
port(8080);
get("/users", (req, res) -> {
return new UserRepository().getUsers();
}, gson::toJson);
}
}
如果您依赖 Tomcat 为您提供连接:它来自一个池。如果您不喜欢,只需使用普通的旧 JDBC 并自己打开该连接(并确保也关闭它)。
对你的问题的回答就到此为止了。现在说说精神:来自池的连接没有错。在所有情况下,正确处理它是您的责任:访问连接并在完成连接后释放它 (close
)。连接来自池还是手动创建都没有区别。
如您所说,性能不是问题:请注意,创建连接可能需要一些时间,因此即使计算机大部分空闲,为每个请求创建一个新连接也可能对性能产生显着影响。您的服务器不会过热,但可能会增加一两秒的请求周转时间。
检查池的配置 - 例如validationQuery
(检测通信故障)或每个连接的使用限制。并确保您不会 运行 因为代码中的错误而陷入这些问题。无论如何,您都需要处理通信错误。而且,无论您是否使用池,处理都没有区别。
编辑:最后:您是否特别确定确实没有通信 link 失败?比如:每天晚上拔下数据库或路由器以连接真空吸尘器? (没有双关语意),防火墙 dropping/resetting 连接等?