【问题标题】:Java RMI call slow first timeJava RMI第一次调用很慢
【发布时间】:2017-05-23 11:36:29
【问题描述】:

我正在为学校开发一个个人项目,我必须使用 RMI 在服务器和客户端之间进行通信。

项目信息

我的项目的目标是在特定时间(纽约证券交易所关闭后)在服务器上检索每天的股票信息(来自纽约证券交易所)。每个股票对象都保存在数据库中。信息通过http检索,与RMI无关。

对于客户,也可以获取股票。当用户想要获取当天的股票对象时,直接从第 3 方服务获取。例如,当用户想要从上个月获取 Google 的股票时,它会通过 RMI 在服务器上请求。服务器将在数据库中查找股票对象并检索股票对象并将其发送给客户端。

问题

当我启动客户端应用程序时,我必须登录。客户端将创建一个包含用户名和密码的用户对象。 当我按下登录按钮时,大约需要 2 分钟才能显示主屏幕。

在我设置 RMI 连接的源代码下方。

服务器(main.java)

public static void main(String[] args) throws UnknownHostException {

    InetAddress IP= InetAddress.getLocalHost();
    System.out.println("IP of my system is := "+IP.getHostAddress());

    if(args.length == 1 && args[0].toLowerCase().equals("local")) {
        System.out.println("Running on localhost");
        System.setProperty("java.rmi.server.hostname", IP.getHostAddress());
    } else {
        System.out.println("rmi hostname is set to 37.97.223.70");
        System.setProperty("java.rmi.server.hostname", "37.97.223.70");
    }

    try {
        Registry reg = LocateRegistry.createRegistry(1099);
        StockAppServer server = StockAppServer.getInstance();
        reg.rebind("StockApp", server);
        System.out.println("StockApp bound for StockAppServer object.");
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

根据启动时传递给应用程序的参数,我将 RMI 主机名设置为我当前的 IP 地址或远程服务器地址。远程服务器地址是静态IP,所以不会改变。

服务器 (StockAppServer.java)

这个类实现了客户端用来调用服务器上的方法的接口。所以这个类扩展了 UnicastRemoteObject。当我启动服务器时,将调用 registerStockTask()。此方法将获取股票代码 (What are ticker symbols?),然后安排一个任务在特定时间获取所有股票对象。

private static StockAppServer _instance;
private List<User> loggedInUsers;
private List<Group> activeGroups;
private List<Notification> registeredNotifications;

private StockAppServer() throws IOException {
    _instance = this;

    this.loggedInUsers = new ArrayList<>();
    this.activeGroups = new ArrayList<>();
    this.registeredNotifications = new ArrayList<>();

    this.registerStockTask();

    clearActiveGroups();
    checkForCompletedNotifications();

    // Start the restful framework to allow incoming connections from the NodeJS server to manage new notification
    Router.getInstance();
}

public static StockAppServer getInstance() {
    try{
        return _instance == null ? new StockAppServer() : _instance;
    } catch (IOException e) {
        e.printStackTrace();
    }

    return null;
}

客户端(main.java)

public static void main(String[] arguments) throws Exception {
    args = arguments;
    Application.launch();
}

@Override
public void start(Stage primaryStage) throws Exception {
    InetAddress IP= InetAddress.getLocalHost();
    System.out.println("IP of my system is := "+IP.getHostAddress());



    if(args.length == 1 && args[0].toLowerCase().equals("local")) {
        // Program started with local command, expect that server is running on local host
        reg = LocateRegistry.getRegistry(IP.getHostAddress(), 1099);
        System.out.println("Attempting to connect to RMI server over 127.0.0.1");
    } else {
        // Program started without additional commands. Except that "the server" is available;
        reg = LocateRegistry.getRegistry("37.97.223.70", 1099);
        System.out.println("Attempting to connect to RMI server over 37.97.223.70");
    }

    try {
        StockApp.getInstance().setServerInterfaces((IStockSend) reg.lookup("StockApp"), (IUserHandling) reg.lookup("StockApp"));
    } catch(RemoteException e) {
        AlertMessage.showException("Unable to connect to server.", e);
    } catch (NotBoundException e) {
        AlertMessage.showException("No server has been found with the name \"StockApp\" on the remote host.\nPlease try again later", e);
    }

    LoginController.showMenu();

    //FileNotFoundException e = new FileNotFoundException("Couldn't find file blabla.txt");
    //AlertMessage.showException("Something went wrong. Please try again later.", e);
}

我如何尝试解决我的问题

当我在本地测试我的应用程序时,没有问题。登录方法将在几毫秒内完成,我将显示在主屏幕上。

  • 我首先关闭了我的 macbook 上的防火墙。没有结果,登录方法仍然需要大约 2 秒。
  • 我关闭了 Ubuntu 服务器的防火墙。没有结果,服务器和macbook上的防火墙都被关闭了。登录方法仍然需要大约 2 秒。
  • 在服务器上运行(感谢 jenkins)另一个(不相关的)程序。该程序使用套接字而不是 RMI。当这个程序没有运行时,登录方法仍然需要大约 2 分钟。
  • 在 StockAppServer.java 中,我调用了以下方法:

    超级(1099); 这与我采取的上述步骤的结果相同。

我不知道我还能尝试什么来解决我的问题。

我尝试为 RMI 部分提供尽可能多的代码。我你需要任何其他源代码,只要问,我可以更新这个问题。此外,源代码可通过 github 获得:https://github.com/juleskreutzer/GSO-Maatwerk。确保使用 -remote 参数运行程序。

更新 1(2017 年 9 月 1 日)

按照 cmets 中 yanys 的要求,我应该运行以下命令:

dscacheutil -q host -a name localhost

这将返回以下输出:

苹果机:

name: localhost
ip_address: 127.0.0.1

Ubuntu:

dscacheutil: command not found

更新 2(2017 年 9 月 1 日)

我咨询了我的 VPS 提供商,我在该 VPS 上运行 Java 服务器。在他们这边,一切都应该没问题。据他们说,这不应该是dns问题。经过一番研究,我发现 RMI 同时使用 DNS 和反向 DNS。在这种情况下,反向 DNS 是问题所在。请参阅我的回答,了解我是如何解决我的问题的。

【问题讨论】:

  • 这将是 DNS 问题,而不是 RMI 问题。
  • @Jules dscacheutil -q host -a name localhost 命令的结果是什么?您的问题可能与“/etc/hosts”文件内容有关。缺少“127.0.0.1 localhost”行等。
  • @yanys - 我用你建议的命令的结果更新了我的问题。

标签: java macos ubuntu rmi


【解决方案1】:

正如 EJP 在有关问题的 cmets 中指出的那样, 是一个 DNS 问题。

我联系了我的托管服务提供商的支持,看看我是否有一些错误的设置。他们帮我解决了这个问题。

首先我们测试了我的VPS的速度,这是1000mbit左右的下载和上传速度。我们检查后,他们说他们这边没有问题。

经过一番研究,我发现 RMI 同时使用 DNS 和反向 DNS。问题是我没有在我的服务器上设置反向 DNS。我已经有一个用于反向 DNS 的域名。

我做了以下事情:

  1. 在我的网站上创建一个指向服务器 IP 地址的 A 记录。我将其命名为 vps.mydomain.com
  2. 在我的服务器控制面板中添加反向DNS
  3. 将我的服务器的主机名更改为 vps.mydomain.com*

*我的服务器运行Ubuntu 16.04,在带有systemd的ubuntu机器上,可以使用命令

sudo hostnamectl set-hostname new-name

更改主机名

【讨论】:

  • Java 出于安全目的使用反向 DNS。不仅仅是 RMI。
猜你喜欢
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多