RavenDB连接建立的“昂贵”操作及Tomcat中连接复用方案咨询
没问题,我来帮你把这些问题捋明白,一步步来:
把RavenDB连接初始化移到ServletContextListener的正确姿势
首先,这个思路完全正确——把RavenDB的核心连接对象初始化放到ServletContextListener里,让Tomcat启动时只执行一次,后续所有服务调用复用这个实例,能大幅提升性能。
具体操作步骤是这样的:
- 创建一个实现
ServletContextListener的类,比如RavenDBInitListener - 在
contextInitialized(ServletContextEvent event)方法里,初始化RavenDB的DocumentStore(这是RavenDB的核心单例对象,必须只创建一次) - 把初始化好的
DocumentStore存入ServletContext,方便后续JAX-RS服务获取 - 在
contextDestroyed(ServletContextEvent event)方法里,关闭DocumentStore,避免资源泄漏
给你个简单的代码示例:
public class RavenDBInitListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent event) { // 初始化DocumentStore,配置服务器地址、数据库名称等 DocumentStore store = new DocumentStore(new String[]{"http://your-ravendb-server:8080"}, "YourDatabaseName"); store.initialize(); // 存入ServletContext,后续服务可以通过key获取 event.getServletContext().setAttribute("RAVEN_DOC_STORE", store); } @Override public void contextDestroyed(ServletContextEvent event) { // 关闭DocumentStore,释放资源 DocumentStore store = (DocumentStore) event.getServletContext().getAttribute("RAVEN_DOC_STORE"); if (store != null) { store.close(); } } }
然后在你的JAX-RS服务里,就可以这样获取复用的连接:
@Path("/your-service") public class YourResource { @Context private ServletContext servletContext; @GET public Response getSomething() { DocumentStore store = (DocumentStore) servletContext.getAttribute("RAVEN_DOC_STORE"); try (Session session = store.openSession()) { // 用session执行数据库操作 // ... return Response.ok().build(); } } }
别忘了在web.xml里注册这个Listener,或者用@WebListener注解(如果你的Tomcat支持Servlet 3.0+的话)。
9年前的连接池文章是否还适用?
这个得看文章针对的RavenDB版本。9年前大概是2015年,当时RavenDB的版本还是3.x甚至更早,那时候可能需要手动配置一些连接池参数。但现在的RavenDB(4.x及以上版本),DocumentStore本身就已经是线程安全的单例对象,内部已经实现了高效的连接池管理,不需要你手动去配置第三方连接池或者复杂的连接池参数了。
所以旧文章里的内容大概率已经过时了,你现在只需要保证DocumentStore是单例、只初始化一次,剩下的连接管理交给RavenDB自己处理就好。
RavenDB连接中的“昂贵”操作
在RavenDB的连接流程里,这些操作是比较耗资源、耗时的,必须尽量避免重复执行:
- 创建
DocumentStore实例:这是最昂贵的一步,因为它要完成与服务器的初始握手、配置序列化规则、初始化内部连接池、加载认证信息等一系列操作,所以必须只创建一次,全程复用。 - 首次建立与服务器的网络连接:第一次从连接池取出连接时,需要完成TCP握手、认证验证等步骤,后续复用连接池里的已建立连接就快很多了。
- 序列化/反序列化框架的初始化:如果你配置了自定义的序列化器(比如Jackson的自定义模块),首次序列化/反序列化对象时会加载相关类、初始化规则,后续复用就高效了。
- 认证令牌的获取(如果启用了安全认证):如果你的RavenDB服务器启用了OAuth或其他认证方式,首次请求时需要和服务器交互获取有效令牌,令牌有效期内可以复用,不用每次都重新请求。
总的来说,核心原则就是:DocumentStore单例化,只初始化一次,每次操作打开/关闭Session(Session是轻量级的,开销很小)。
内容的提问来源于stack exchange,提问作者Hiro Protagonist
相关产品推荐
相关产品推荐

