2014-11-25 2 views
1

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

Что я хочу сделать, это нечто похожее на this, но с RMI.

В принципе, прекратите принимать/обрабатывать запросы, если насыщенность сервера достигнута, чтобы он мог обрабатывать текущие.

Возможно ли это, или мне действительно нужно использовать сокеты для достижения этого?

Заранее спасибо.

EDIT: Я также должен знать, сколько запросов было отклонено где-то (может быть на стороне клиента или на стороне сервера)

+0

TCP уже выполнит это, если очередь задержек заполнится. Вам не нужно предпринимать никаких специальных действий. – EJP

+0

Но мне нужно знать, сколько запросов было отклонено сервером. Если это так, можно проверить или проверить, заполнена ли эта очередь отставания на стороне «клиента»? –

+0

Вам нужно знать, почему? И, конечно, если сервер отклоняет запросы, вы не можете знать ничего * о сервере с конца клиента. – EJP

ответ

0

RMI предлагает способ контролировать создание сокета сервера, если вы контролируете создание клиента -сервер, вы можете решить, следует ли обслуживать входящий запрос или нет, и из-за того, что вы можете контролировать отказ от обслуживания. здесь вам нужно расширить ServerSocket. И если вы хотите отклонить запрос метода invoke, вы можете использовать прокси-объект.

public class T { 

    public static void main(String[] a) throws IOException { 
     Queue<Socket> socks = new ConcurrentLinkedQueue<>(); 

     Registry registry = LocateRegistry.createRegistry(1099); 
     IserverImpl roImpl = new IserverImpl(); 
     IService ro = Proxy.newProxyInstance(registry.getClass().getClassLoader(), 
         new Class[]{IService.class}, 
         (proxy, method, args) -> { 
          if (isServerSaturationReached()) { 
           logRejection(method); 
           throw ReqRejectedByServerException(); 
          } 
          return method.invoke(roImpl, args); 
         }); 

     Remote expRO = UnicastRemoteObject.exportObject(ro, 1100, null, 
         new RMIServerSocketFactory() { 
          @Override 
          public ServerSocket createServerSocket(int port) throws IOException { 
           return new MyServerSocket(port, socks); 
          } 
         }); 
     registry.bind("ro", expRO); 

     Thread socksMgr = new Thread() { 
      @Override 
      public void run() { 
       while (true) { 
        try { 
         Thread.sleep(30000); 
         int sSize = socks.size(); 
         for (int i = 0; i < sSize; i++) { 
          final Socket s = socks.remove(); 
          try { 
           // server side RMI socket will be closed if client close socket 
           if (!s.isClosed()) 
            socks.offer(s); 
          } catch (Exception e) { 
           e.printStackTrace(); 
          } 
         } 
         sSize = socks.size(); 
         if (isServerSaturationReached(sSize)) 
          for (int i = 0; i < sSize/10; i++) { 
           try { 
            final Socket sockToReject = socks.remove(); 
            reject(sockToReject); // sockToReject.close(); 
            logRejection(sockToReject); 
           } catch (IOException e) { 
           } 
          } 
        } catch (InterruptedException e) { 
         return; 
        } 
       } 
      } 
     }; 
     socksMgr.setPriority(Thread.MAX_PRIORITY); 
     socksMgr.setDaemon(true); 
     socksMgr.start(); 
    } 

    public static class MyServerSocket extends ServerSocket { 

     private Queue<Socket> socks; 

     public MyServerSocket(int port, Queue<Socket> socks) throws IOException { 
      super(port); 
      this.socks = socks; 
     } 

     @Override 
     public Socket accept() throws IOException { 
      while (!super.isClosed()) { 
       Socket a = super.accept(); 
       if (isServerSaturationReached(socks.size())) { 
        reject(a); // a.close(); 
        logRejection(a); 
        //... 
       } else { 
        socks.offer(a); 
        return a; 
       } 
      } 
      throw new SocketException("Socket is closed"); 
     } 
    } 
} 
+0

Это не подходит. Из-за пула соединений на стороне клиента отнюдь не каждый новый запрос приходит к новому соединению. Сервер все еще может насыщаться. – EJP

+0

@EJP - это способ управления соединениями на стороне клиента, если ваше «насыщение сервера» является ресурсом или ресурсом процессора, его легко контролировать (пул потоков или еще что-то еще), и это не имеет ничего общего с RMI. здесь, на мой взгляд, «насыщенность сервера» означает слишком много запросов RMI-client-connection-request. – mysh

+0

Нет, это не «способ контролировать соединения на стороне клиента». Это способ управления * новыми * * входящими * соединениями * на стороне сервера. * Связи на стороне клиента, которые уже существуют, не контролируются этим механизмом, и цель OP по отказу в обслуживании при насыщении сервера не встретил. В частности, чтобы использовать собственную бессмысленную формулировку, она не контролирует «слишком много запросов клиента-клиента RMI», поскольку это не унитарная концепция. Одно соединение может обслуживать несколько запросов через пул соединений на клиенте. Ваш ответ и комментарий демонстрируют неосознанное понимание этого. – EJP