未能创建子事件 loop/failed 以打开一个新的 selector/Too 许多打开的文件

failed to create a child event loop/failed to open a new selector/Too many open files

有 30 个或更多并发请求时,我收到类似 "failed to create a child event loop/failed to open a new selector/Too many open files" 的错误...如何解决上述错误?我做错了什么吗?我正在使用 Spring 引导和 Java cassandra 驱动程序。 下面是连接文件

public class Connection {

public static Session getConnection() {

    final Cluster cluster = Cluster.builder().addContactPoint(ConnectionBean.getCASSANDRA_DB_IP())
            .withQueryOptions(new QueryOptions().setConsistencyLevel(ConsistencyLevel.LOCAL_ONE))
            .withCredentials(ConnectionBean.getCASSANDRA_USER(), ConnectionBean.getCASSANDRA_PASSWORD())
            .withPoolingOptions(poolingOptions)
            .build();
    final Session session = cluster.connect(ConnectionBean.getCASSANDRA_DB_NAME());
    return session;
}

}

下面是我在Connection文件中使用的ConnectionBean文件:

public  class ConnectionBean {

public static   String CASSANDRA_DB_IP;
public static String CASSANDRA_DB_NAME;
public static  String CASSANDRA_USER;
public static String CASSANDRA_PASSWORD;

public ConnectionBean() {

}
public ConnectionBean(String CASSANDRA_DB_IP,String CASSANDRA_DB_NAME,String CASSANDRA_USER,String CASSANDRA_PASSWORD) {
this.CASSANDRA_DB_IP=CASSANDRA_DB_IP;
this.CASSANDRA_DB_NAME=CASSANDRA_DB_NAME;
this.CASSANDRA_USER=CASSANDRA_USER;
this.CASSANDRA_PASSWORD=CASSANDRA_PASSWORD;
}

public static String getCASSANDRA_DB_IP() {
    return CASSANDRA_DB_IP;
}
public static void setCASSANDRA_DB_IP(String cASSANDRA_DB_IP) {
    CASSANDRA_DB_IP = cASSANDRA_DB_IP;
}
public static String getCASSANDRA_DB_NAME() {
    return CASSANDRA_DB_NAME;
}
public static void setCASSANDRA_DB_NAME(String cASSANDRA_DB_NAME) {
    CASSANDRA_DB_NAME = cASSANDRA_DB_NAME;
}
public static String getCASSANDRA_USER() {
    return CASSANDRA_USER;
}
public static void setCASSANDRA_USER(String cASSANDRA_USER) {
    CASSANDRA_USER = cASSANDRA_USER;
}
public static String getCASSANDRA_PASSWORD() {
    return CASSANDRA_PASSWORD;
}
public static void setCASSANDRA_PASSWORD(String cASSANDRA_PASSWORD) {
    CASSANDRA_PASSWORD = cASSANDRA_PASSWORD;
}   

}

下面是初始化 ConnectionBean 变量的class:

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final String LOGIN_PROCESSING_URL = "/login";
private static final String LOGIN_FAILURE_URL = "/login?error";
private static final String LOGIN_URL = "/login";

@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;

@Autowired
private DataSource dataSource;

@Value("${spring.queries.users-query}")
private String usersQuery;

@Value("${spring.queries.roles-query}")
private String rolesQuery;

@Value("${CASSANDRA_DB_IP}")
public String CASSANDRA_DB_IP;

@Value("${CASSANDRA_DB_NAME}")
public String CASSANDRA_DB_NAME;

@Value("${CASSANDRA_USER}")
public String CASSANDRA_USER;

@Value("${CASSANDRA_PASSWORD}")
public String CASSANDRA_PASSWORD;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    ConnectionBean cb = new ConnectionBean(CASSANDRA_DB_IP, CASSANDRA_DB_NAME, CASSANDRA_USER, CASSANDRA_PASSWORD);

    auth.jdbcAuthentication().usersByUsernameQuery(usersQuery).authoritiesByUsernameQuery(rolesQuery)
            .dataSource(dataSource).passwordEncoder(bCryptPasswordEncoder);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    // Not using Spring CSRF here to be able to use plain HTML for the login page

    http.csrf().disable()

            // Register our CustomRequestCache, that saves unauthorized access attempts, so
            // the user is redirected after login.
            .requestCache().requestCache(new CustomRequestCache())

            // Restrict access to our application.
            .and().authorizeRequests()

            // Allow all flow internal requests.
            .requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll()

            // Allow all requests by logged in users.
            .anyRequest().authenticated()

            // Configure the login page.
            .and().formLogin().loginPage(LOGIN_URL).permitAll().loginProcessingUrl(LOGIN_PROCESSING_URL)
            .failureUrl(LOGIN_FAILURE_URL)

            // Register the success handler that redirects users to the page they last tried
            // to access
            .successHandler(new SavedRequestAwareAuthenticationSuccessHandler())

            // Configure logout
            .and().logout().logoutSuccessUrl(LOGOUT_SUCCESS_URL);
}

/**
 * Allows access to static resources, bypassing Spring security.
 */
@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers(
            // Vaadin Flow static resources
            "/VAADIN/**",

            // the standard favicon URI
            "/favicon.ico",

            // web application manifest
            "/manifest.json", "/sw.js", "/offline-page.html",

            // icons and images
            "/icons/**", "/images/**",

            // (development mode) static resources
            "/frontend/**",

            // (development mode) webjars
            "/webjars/**",

            // (development mode) H2 debugging console
            "/h2-console/**",

            // (production mode) static resources
            "/frontend-es5/**", "/frontend-es6/**");
}

}

最后,下面是我查询cassandra数据的class:

public class getData {
Session session;

public getData(){
    session = Connection.getConnection();
    getDataTable();
}

private void getDataTable() {
    try {
        String query = "SELECT * FROM tableName";
        ResultSet rs = session.execute(query);
        for (Row row : rs) {
            /*Do some stuff here using row*/
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

如果每个请求都调用 getConnection(),则每次都会创建一个新的 Cluster 实例。

不鼓励这样做,因为在您的客户端和 C* 节点之间为每个 Cluster 实例创建了一个连接,并且对于每个 Session 至少为每个实例创建了一个连接池C*节点。

如果您在请求完成后不关闭 Cluster 实例,这些连接将保持打开状态。在多次请求后,您将打开如此多的连接,以至于 运行 超出 OS.

中的文件描述符

要解决此问题,请仅创建一个 ClusterSession 实例并在请求之间重复使用它。 4 simple rules when using the DataStax drivers for Cassandra:

中概述了此策略
  1. Use one Cluster instance per (physical) cluster (per application lifetime)
  2. Use at most one Session per keyspace, or use a single Session and explicitely specify the keyspace in your queries