0

当有 30 个或更多并发请求时,我收到诸如“无法创建子事件循环/无法打开新选择器/打开的文件太多”之类的错误......如何解决上述错误?我做错什么了吗?我正在使用 Spring boot 和 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 变量的类:

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 数据的类:

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();
    }
}

}

4

1 回答 1

1

If getConnection() is being invoked for every request, you are creating a new Cluster instance each time.

This is discouraged because one connection is created between your client and a C* node for each Cluster instance, and for each Session a connection pool of at least one connection is created for each C* node.

If you are not closing your Cluster instances after a request completes, these connections will remain open. After a number of requests, you'll have so many connections open that you will run out of file descriptors in your OS.

To resolve this issue, create only one Cluster and Session instance and reuse it between requests. This strategy is outlined in 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
于 2018-07-19T13:50:39.953 回答