RMI offers you a way to control the server socket creation, if you control the creation of client-server socket, you can decide whether to serve the incoming request or not, and of cause you can monitor rejections of service. here you need to extend ServerSocket.
And if you want to reject "method invoke request", you can use a proxy object.
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");
}
}
}