2017-01-09 10 views
1

Я работаю над личным проектом для школы, где у меня есть RMI для связи между сервером и клиентом.Java RMI call slow first time

Информация о проекте

Целью моего проекта является получение информации запаса (от NYSE) за каждый день на сервере в определенное время (после того, как NYSE закрыт). Каждый объект запаса сохраняется в базе данных. Информация извлекается по http и не имеет ничего общего с RMI.

Для клиента также можно получить акции. Когда пользователь хочет получить объект запаса на текущий день, он напрямую извлекается из 3-го партийного сервиса. Когда пользователь, например, хочет получить товар Google за последний месяц, он запрашивается на сервере через RMI. Сервер будет искать объект запаса в базе данных и получить объект Stock и отправить его клиенту.

Проблема

При запуске клиентского приложения, я должен войти в систему. Клиент создаст объект User, содержащий имя пользователя и пароль. Когда я нажимаю кнопку входа в систему, это займет около 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; 
} 

Client (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.

Update 1 (9-1-2017)

Как yanys запрошенные в комментариях, я должен выполнить следующую команду:

dscacheutil -q -a пройдет имя локального

это возвращает следующий результат:

Mac:

name: localhost 
ip_address: 127.0.0.1 

Ubuntu:

dscacheutil: command not found 

Update 2 (9-1-2017)

Я проверил с поставщиком моего VPS, где я бегу сервер Java на. На их стороне все должно быть в порядке. По их словам, это не должно быть проблемой DNS. После некоторых исследований я узнал, что RMI использует DNS и обратный DNS. В этом случае обратная DNS была проблемой. Пожалуйста, см. Мой ответ о том, как я решил свою проблему.

+1

Это будет poblem DNS, а не проблема RMI. – EJP

+0

@Jules Что является результатом команды 'dscacheutil -q host -a name localhost'? Ваша проблема может иметь какое-то отношение к содержимому файла/etc/hosts. Отсутствует строка «127.0.0.1 localhost» или аналогичная. –

+0

@yanys - Я обновил свой вопрос с помощью команды, которую вы предложили. – Jules

ответ

0

Как EJP указал в комментариях к вопросу, он был проблема DNS.

Я связался с поддержкой моего хостинг-провайдера, чтобы узнать, были ли у меня неправильные настройки. Они очень помогли мне в решении этой проблемы.

Сначала мы протестировали скорость моего VPS, это около 1000 Мбит скорости загрузки и выгрузки. После того, как мы проверили это, они сказали, что на их стороне нет ничего плохого.

После выполнения некоторых исследований выяснилось, что RMI использует DNS и обратный DNS. Проблема в том, что я не настроил обратный DNS на моем сервере. У меня уже есть доменное имя для обратного DNS.

я чем сделал следующее:

  1. Создать A-запись на моем сайте, который указывает на IP-адрес сервера. Я назвал его vps.mydomain.com
  2. Добавить обратный DNS на панели управления моего сервера
  3. Измените имя хоста моего сервера на vps.mydomain.ком *

* Мой сервер работает Ubuntu 16,04, на Ubuntu машинах с Systemd, вы можете использовать команду hostnamectl установить имя-хоста нового имя-

SUDO

изменить имя хоста

+0

* Java * использует обратный DNS для целей безопасности. Это не просто RMI. – EJP