【问题标题】:Connection pooling in Spark Java frameworkSpark Java 框架中的连接池
【发布时间】:2017-08-15 20:58:36
【问题描述】:

Java Spark 框架使用嵌入式 Jetty 作为 Web 服务器。 Jetty 支持使用 HikariCP 和 在 XML 文件中提供 configuration options。然而,根据 对于these posts,Spark 确实允许配置 Jetty。 有很多使用 Spark 的示例,但它们要么没有 使用数据库或使用DriverManager连接数据库。

是否可以通过数据源配置连接池 和 Spark 中的 JNDI?如果有,怎么做?

【问题讨论】:

  • 你搞清楚了吗?我也面临同样的问题。
  • 没有。我已经悬赏了这个问题。
  • github 中有关于此功能请求的线程。如果你擅长java,那就看看吧。
  • 我查看了线程(您在these posts 中提到)并提交,它为使用JettyServerFactory 的嵌入式码头使用的线程提供了灵活性。这不是解决连接池的问题。
  • @JanBodnar 我在 github 上打开了问题:github.com/perwendel/spark/issues/833

标签: java jetty jndi connection-pooling spark-java


【解决方案1】:

我在 Spark Java 中使用 HikariCP 为 MariaDB 配置了池。我没有使用 Jetty,而是使用了 Apache Tomcat。下面是一些sn-ps的代码:

src/main/resources/mysql-connection.properties

dataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
dataSource.url=<url>
dataSource.user=<user>
dataSource.password=<password>
dataSource.cachePrepStmts=true
dataSource.prepStmtCacheSize=100
dataSource.prepStmtCacheSqlLimit=2048
dataSource.useServerPrepStmts=true
maximumPoolSize=10

com/example/app/DataSourceFactory.java

public final class DataSourceFactory {

    static final Logger LOG = LoggerFactory.getLogger(DataSourceFactory.class);

    private static DataSource mySQLDataSource;

    private DataSourceFactory() {
    }

    //returns javax.sql.DataSource
    public static DataSource getMySQLDataSource() {
        if (mySQLDataSource == null) {
            synchronized (DataSourceFactory.class) {
                if (mySQLDataSource == null) {
                    mySQLDataSource = getDataSource("mysql-connection.properties");
                }
            }
        }
        return mySQLDataSource;
    }

    // method to create the DataSource based on configuration
    private static DataSource getDataSource(String configurationProperties) {
        Properties conf = new Properties();
        try {
            conf.load(DataSourceFactory.class.getClassLoader().getResourceAsStream(configurationProperties));
        } catch (IOException e) {
            LOG.error("Can't locate database configuration", e);
        }
        HikariConfig config = new HikariConfig(conf);
        HikariDataSource dataSource = new HikariDataSource(config);
        LOG.info("DataSource[" + configurationProperties + "] created " + dataSource);
        return dataSource;
    }

}

WebContent/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee                              
    http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">

    <display-name>My Spark App</display-name>
    <filter>
        <filter-name>SparkFilter</filter-name>
        <filter-class>spark.servlet.SparkFilter</filter-class>
        <init-param>
            <param-name>applicationClass</param-name>
            <param-value>com.example.app.MySparkApp</param-value>
            <!-- MySparkApp implements spark.servlet.SparkApplication -->
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>SparkFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <listener>
        <listener-class>com.example.app.AppServletContextListener</listener-class>
    </listener>
</web-app>

com/example/app/AppServletContextListener.java

public class AppServletContextListener implements ServletContextListener {

    static final Logger LOG = LoggerFactory.getLogger(AppServletContextListener.class);

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        LOG.info("contextInitialized...");
    }

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        LOG.info("contextDestroyed...");
        try {
            if (DataSourceFactory.getMySQLDataSource() != null) {
                DataSourceFactory.getMySQLDataSource().unwrap(HikariDataSource.class).close();
            }

        } catch (SQLException e) {
            LOG.error("Problem closing HikariCP pool", e);
        }

    }

}

最后你可以通过调用DataSourceFactory.getMySQLDataSource().getConnection()来获得一个池化的java.sql.Connection

【讨论】:

  • 您好,感谢您的回答。我知道Tomcat是可能的。问题是如何使用嵌入式 Jetty 来做到这一点,这是 Spark 的默认设置。
  • 这是在说apache-spark??
  • @BrendanM sparkjava.com
【解决方案2】:

应该可以,但你必须:

  1. 配置池
  2. 保持对数据源的静态引用
  3. 找到启动/连接数据库的位置,更重要的是找到关闭/释放池的方法

第 1) 点和第 2) 点可以很简单:

static final HikariDataSource datasource = new HikariDataSource(new HikariConfig());

不知道 Sparkjava 是否支持启动/停止事件。我帮不了你。

或者,您可以尝试http://jooby.org(我是作者)和jdbc module

{
  use(new Jdbc());

  get("/db", () -> {
    DataSource ds = require(DataSource.class);
  });
}

Jdbc 模块为您提供具有合理默认选项的 HikariDatasource,但同时您可以通过 application.conf 文件自定义池。

还有一些高级的jdbc modules,比如Hibernate、Ebean、jOOQ、Jdbi等......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 2011-10-13
    • 2013-04-08
    • 1970-01-01
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多