1

我正在开发一个将 UniVerse 数据库连接到 REST 端点的 API。问题是我们没有使用 Java 的 UniVerse 库进行本地连接池的许可。

该软件是使用 Spring Boot 用 Ja​​va 开发的,以及我打开会话到 Universe 的方式

uniSession = uniJava.openSession();
 uniSession.setHostName(server);
 uniSession.setUserName(userName);
 uniSession.setPassword(password);
 uniSession.setAccountPath(accountPath);
 uniSession.connect(); 

我对其进行迭代并将会话保存在列表“freeSession”中,当我收到请求时,我从该列表中弹出一个会话,将其移动到“occupiedSession”,使用它并返回到“freeSession”。

但问题是在 sessios 列表中都是“相同的”。我的意思是,我无法接收并发请求,因为我的 API 只有“一个会话”来与 UniVerse 服务器交互。

4

2 回答 2

1

尝试在 UniDK 5.2.1 中升级到最新版本的 UniObjects for Java。我猜想使用 UniJava 可能在旧版本中表现出这种行为。只要您只是运行 BASIC 程序,我猜您不会遇到与 10.1.21 的任何兼容性问题:

  1. 访问https://rbc.rocketsoftware.com/u2bcesdinternal.asp?pid=100000047043&product=U2CL并下载 U2 Current Clients 安装程序

或(长期)

  1. 访问https://rbc.rocketsoftware.com/buildmatrix.asp
  2. 为产品选择 U2 客户端,为平台选择 Windows
  3. 使用下载列中的产品链接下载安装程序

老实说,我正在使用 UniObjects for Java(在 UniDK 5.2.1 中)从 Spring Boot 应用程序连接到 Universe,并且我能够使用与您类似的代码创建和维护多个并行连接。如果我同时收到十个 Web 请求,我可以在 Universe 中看到十个独立的 uvcs/defcs 连接。我唯一不同的是使用最新的罐子,我只是创建一个 UniSession 的新实例(然后像你一样调用连接):

UniSession uniSession = new UniSession();

代替

UniSession uniSession = uniJava.openSession();

然而,最新版本的 UniJava 似乎与创建一个新实例基本相同,但有一些额外的日志记录和跟踪。

我确实有人在 Rocket 告诉我,正常的 Universe 许可协议禁止重新创建连接池,从而迫使您购买连接池许可证。我没有方便确认的许可证。但是,我不建议您在与 Rocket 会面的情况下购买连接池许可证,以讨论您的应用程序在扩展时的具体要求。根据负载、持久性和性能要求,您可能需要将读取操作分散到多个 Universe 复制中,已发布的连接池许可模型无法很好地/成本有效地支持此操作。

于 2022-01-17T23:16:32.447 回答
0

已经有一段时间了,我再也无法访问代码了,但几年前我处理过类似的问题。该解决方案使用信号量来帮助实现并发性。创建一个可以全局共享的连接池类。当调用代码需要一个 unisession 时,如果可用,连接池会抓取一个,否则它会阻塞调用线程,直到有一个可用。当然,您不想像本例中那样硬编码计数或连接参数(其中大部分是从信号量 javadocs 复制的)。

import java.util.concurrent.Semaphore;

public class ConnectionPool
{
    private static final int COUNT = 5;
    private static final ConnectionPool INSTANCE = new ConnectionPool();

    private final Semaphore available = new Semaphore(COUNT, true);
    protected UniSession[] items =  new UniSession[COUNT];

    protected boolean[] used = new boolean[COUNT];
    protected UniJava uniJava = new UniJava();

    private ConnectionPool() {
        for (int i = 0; i < COUNT; i++) {
            items[i] = uniJava.openSession();
            items[i].setHostName("server name");
            items[i].setUserName("user name");
            items[i].setPassword("password");
            items[i].setAccountPath("account path");
            items[i].connect();
        }
    }

    public static ConnectionPool getInstance() {
        return INSTANCE;
    }

    public UniSession borrow() throws InterruptedException {
        available.acquire();
        return getNextAvailableItem();
    }

    public void release(UniSession session) {
        if (markAsUnused(session))
            available.release();
    }

    protected synchronized UniSession getNextAvailableItem() {
        for (int i = 0; i < COUNT; ++i) {
            if (!used[i]) {
                used[i] = true;
                return items[i];
            }
        }
        return null;
    }

    protected synchronized boolean markAsUnused(Object item) {
        for (int i = 0; i < COUNT; ++i) {
            if (item == items[i]) {
                if (used[i]) {
                    used[i] = false;
                    return true;
                } else
                    return false;
            }
        }
        return false;
    }

}

然后在您的 API 代码中,当您需要一个 unisession 时,您会从池中借用一个,确保在完成后释放它。像这样的东西:

UniSession uniSession = null;

try {
    uniSession = ConnectionPool.getInstance().borrow();
    
    // do work
    
} finally {
    ConnectionPool.getInstance().release(uniSession);
}

这使您的应用程序可以重用会话池,并且会话数永远不会超过您指定的计数。

于 2022-01-18T17:16:33.027 回答