2.0版本最大支持同时打开多少个session?

  • nebula 版本:2.0GA
  • 部署方式(分布式 / 单机 / Docker / DBaaS):分布式,自行编译
  • 是否为线上版本:Y
  • 硬件信息
    • 磁盘( 推荐使用 SSD):SSD
    • CPU、内存信息:40core 128GB

我的问题一方面关于Java客户端,另一方面关于nebula本身
1、2.0的Java客户端是有连接池实现的,那么我在给NebulaPoolConfig设置maxConnSize时,影响的是连接池中的什么东西呢?是否是连接池中的最大连接数==maxConnSize?
2、对于一个连接,可以在它上面同时打开多少个session?如果我同时在一个连接池上getSession(),且同时getSession()的线程数量>maxConnSize,会发生什么?
3、nebula服务端支持同时维护最多多少个session?如果我有很多服务在利用连接池同时打开很多session,随着服务数量的增加,打开的session数量也会变多,这样最终会出什么问题吗?是会崩掉还是会阻塞后面的session?

2 个赞

1、2.0的Java客户端是有连接池实现的,那么我在给NebulaPoolConfig设置maxConnSize时,影响的是连接池中的什么东西呢?是否是连接池中的最大连接数==maxConnSize?

这个maxConnSize 就是池里面会帮你一直保管的最大连接数,假如你设置很大,那么占用系统资源,你就根据需求设置就好。

2、对于一个连接,可以在它上面同时打开多少个session?如果我同时在一个连接池上getSession(),且同时getSession()的线程数量>maxConnSize,会发生什么?

一个连接只会被一个session持有,这个是池给你保证的,假如你调用getSession 的次数超过 maxConnSize,那么会报错,报错是提示没有连接了,假如你每次调用完 getSession 用完session会release,那么你无限制调用 getSession 都是没问题的。因为池里的连接是可以重复用的,release表示这个session释放连接,同时也表示这个session已经不能再用。

3、nebula服务端支持同时维护最多多少个session?如果我有很多服务在利用连接池同时打开很多session,随着服务数量的增加,打开的session数量也会变多,这样最终会出什么问题吗?是会崩掉还是会阻塞后面的session?

nebula服务端当前版本没有限制session数量,假如你的连接不断产生又不关闭,那么最终会导致系统资源不够,服务无法提供正常服务。

2 个赞

清楚了,谢谢

@dingding
连接池的用法是不是类似这样,在项目启动时初始化数据库,并且选择图空间use myspace,在每次查询完后session.release() 。在app结束前执行pool.close()

public static void main(String[] args) {
        NebulaPool pool = new NebulaPool();
        Session session = null;
        try {
            NebulaPoolConfig nebulaPoolConfig = new NebulaPoolConfig();
            nebulaPoolConfig.setMaxConnSize(100);
            List<HostAddress> addresses = Arrays.asList(new HostAddress("172.80.1.2", 9669),
                    new HostAddress("172.80.1.3", 9669));
            pool.init(addresses, nebulaPoolConfig);
            session = pool.getSession("root", "nebula", false);
            {
                String createSchema = "CREATE SPACE IF NOT EXISTS test; "
                                      + "USE test;"
                                      + "CREATE TAG IF NOT EXISTS person(name string, age int);"
                                      + "CREATE EDGE IF NOT EXISTS like(likeness double)";
                ResultSet resp = session.execute(createSchema);
                if (!resp.isSucceeded()) {
                    log.error(String.format("Execute: `%s', failed: %s",
                        createSchema, resp.getErrorMessage()));
                    System.exit(1);
                }
            }

            TimeUnit.SECONDS.sleep(5);
            {
                String insertVertexes = "INSERT VERTEX person(name, age) VALUES "
                    + "'Bob':('Bob', 10), "
                    + "'Lily':('Lily', 9), "
                    + "'Tom':('Tom', 10), "
                    + "'Jerry':('Jerry', 13), "
                    + "'John':('John', 11);";
                ResultSet resp = session.execute(insertVertexes);
                if (!resp.isSucceeded()) {
                    log.error(String.format("Execute: `%s', failed: %s",
                        insertVertexes, resp.getErrorMessage()));
                    System.exit(1);
                }
            }

            {
                String insertEdges = "INSERT EDGE like(likeness) VALUES "
                    + "'Bob'->'Lily':(80.0), "
                    + "'Bob'->'Tom':(70.0), "
                    + "'Lily'->'Jerry':(84.0), "
                    + "'Tom'->'Jerry':(68.3), "
                    + "'Bob'->'John':(97.2);";
                ResultSet resp = session.execute(insertEdges);
                if (!resp.isSucceeded()) {
                    log.error(String.format("Execute: `%s', failed: %s",
                        insertEdges, resp.getErrorMessage()));
                    System.exit(1);
                }
            }

            {
                String query = "GO FROM \"Bob\" OVER like "
                    + "YIELD $^.person.name, $^.person.age, like.likeness";
                ResultSet resp = session.execute(query);
                if (!resp.isSucceeded()) {
                    log.error(String.format("Execute: `%s', failed: %s",
                        query, resp.getErrorMessage()));
                    System.exit(1);
                }
                printResult(resp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.release();
            }
            pool.close();
        }
    }

假如你release 了 session,那么你下次拿session的space需要你重新执行use space

那如果在使用session时抛了异常是不是就不能用这个session了?

有两种方案
1.应用启动后使用一个session。完成整个应用的数据库操作。
2.每次与数据库交互都创建一个session,执行use myspace,ngql,一次交互完后就session.release();
@dingding 您更倾向与选择哪种使用方式呢?

看什么异常,超时异常是没问题的,假如是连接断开,那就需要重新拿一个

我倾向第一种,但是对用户来说,使用就不是很方便,因为自己要维护session的生命周期。

1.主要是每次使用前判断一下sesion是否有效,如果没有无效了要先创建一个。但是按照这种方案要这个pool还有什么意义?全系统用的都是一个session啊。如果sesion断了还要手动去获取。这个没有pool有什么区别?

2.有没有java的 Object Graph Mapping (OGM) 框架库推荐呢

1.主要是每次使用前判断一下sesion是否有效,如果没有无效了要先创建一个。但是按照这种方案要这个pool还有什么意义?

现在session支持重连的,但是有可能所有服务异常了,那么所有连接都是不能用的。所以pool是能保证多个服务有部分服务异常的时候,还能保证你的session正常工作。

2.有没有java的 Object Graph Mapping (OGM) 框架库推荐呢

还没提供,过段时间会提供。

这个就相当于连接数据库的代价了,sesion和pool合二为一也可以实现了,分成两个有什么优势呢?pool会一直和保持应用和nebula每个结点的网络连接吗?还是只要在获取sesion的时候才会连接。

  1. pool会 缓存maxConnSize 个sesion,那么这maxConnSize个session不管有没有用,都合nebla保持连接吗?
    3.怎样在nebula查看连接?

pool 里面的连接是会重复利用的,当你的session释放了连接,那么从池里拿新的session就可以复用这个连接了。

pool会 缓存maxConnSize 个sesion,那么这maxConnSize个session不管有没有用,都合nebla保持连接吗?

每个连接有idle time的,假如你的业务持续有 maxConnSize 个并发请求,那么这些连接就可以一直用,假如你的业务系统流量不清楚,有时候一个,有时候几个,最多的时候是maxConnSize,这个时间很不确定,那么为了避免连接的浪费,你可以设置idle time,超过idle time的连接会被释放。

3.怎样在nebula查看连接?

目前池提供这三个接口可以获取一些连接状态:
getActiveConnNum()
getIdleConnNum()
getWaitersNum()

1.在nebula-graph可以看吗?如果是多个应用连一个图数据库的话,在nebula上看看更全面
2.一般的关系型数据的连接池是向连接池借用连接,用完即还。nebula的连接池还不是这个逻辑,一时还转不过这个弯。

master上面是可以,有 show sessions命令看

2.一般的关系型数据的连接池是向连接池借用连接,用完即还。nebula的连接池还不是这个逻辑,一时还转不过这个弯。

nebula的也是可以这样用,你要用完就还也是可以的,只是后面需要重新use space

好,其实其它问题都说清楚了。都没有问题了。非常感谢您的耐心解答!!


再问一个。每次都 获取session-use space-ngql-session.release,对于性能有没有影响呢?如果有影响,影响的程度是什么样的呢?

image
怎样判断这个session能不能使用呢?
是通过执行execute然后看报错信息吗?
还是看ping能不能ping通?
这里应该有一个判断session状态的方法吧

这个过程client和graphd会多三次io交互,第一次是检测连接是否是正常的,第二次是做一次认证获取session id,第三次是 use space,这是client和graphd的三次io,graphd会和metad有两次io,第一次是生存session id,第二次是获取space信息。

只要你的session不调用release,你就可以认为它一直可用,这是由池和服务端保证它连接的有效和session的有效。

你这么说,我倒是觉得很神奇了。用户也很方便。用户只用在项目启动时获取一个session然后随便用了。