org.jgroups.tests.UnicastTestRpc Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
package org.jgroups.tests;
import org.jgroups.*;
import org.jgroups.blocks.MethodCall;
import org.jgroups.blocks.RequestOptions;
import org.jgroups.blocks.ResponseMode;
import org.jgroups.blocks.RpcDispatcher;
import org.jgroups.jmx.JmxConfigurator;
import org.jgroups.protocols.relay.RELAY;
import org.jgroups.protocols.relay.SiteMaster;
import org.jgroups.util.Util;
import javax.management.MBeanServer;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Tests performance of unicast RPCs between a caller and a recipient
*
* @author Bela Ban
*/
public class UnicastTestRpc implements Receiver {
private JChannel channel;
private Address local_addr;
private RpcDispatcher disp;
private String groupname="UTestRpc";
private boolean sync=true, oob=true, anycasting=false;
private int num_threads=25;
private int num_msgs=100000, msg_size=1000, print=num_msgs / 10;
private int anycast_count=1;
private final Collection anycast_mbrs=new ArrayList<>();
private Address destination=null;
private static final Method RECEIVE;
private static final Method[] METHODS=new Method[1];
protected final AtomicInteger num_requests=new AtomicInteger(0);
static {
try {
RECEIVE=UnicastTestRpc.class.getMethod("receiveData", byte[].class);
METHODS[0]=RECEIVE;
}
catch(NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public void init(String props, final String name, String cluster_name) throws Exception {
if(cluster_name != null)
groupname=cluster_name;
channel=new JChannel(props);
if(name != null)
channel.setName(name);
disp=new RpcDispatcher(channel, this).setMethodLookup(id -> METHODS[id]).setReceiver(this);
channel.connect(groupname);
local_addr=channel.getAddress();
try {
MBeanServer server=Util.getMBeanServer();
JmxConfigurator.registerChannel(channel, server, "jgroups", channel.getClusterName(), true);
}
catch(Throwable ex) {
System.err.println("registering the channel in JMX failed: " + ex);
}
}
void stop() {
if(disp != null)
disp.stop();
Util.close(channel);
}
@SuppressWarnings("UnusedParameters")
public static void receiveData(byte[] data) {
;
}
public void viewAccepted(View new_view) {
System.out.println("** view: " + new_view);
}
public void eventLoop() throws Throwable {
int c;
while(true) {
System.out.print("[1] Send msgs [2] Print view [3] Set sender threads (" + num_threads +
") [4] Set num msgs (" + num_msgs + ") " +
"\n[5] Set msg size (" + Util.printBytes(msg_size) + ")" +
" [6] Set anycast count (" + anycast_count + ")" +
"\n[o] Toggle OOB (" + oob + ") [s] Toggle sync (" + sync + ") [a] Toggle anycasting (" + anycasting + ")" +
"\n[q] Quit\n");
System.out.flush();
c=System.in.read();
switch(c) {
case -1:
break;
case '1':
try {
invokeRpcs();
}
catch(Throwable t) {
System.err.println(t);
}
break;
case '2':
printView();
break;
case '3':
setSenderThreads();
break;
case '4':
setNumMessages();
break;
case '5':
setMessageSize();
break;
case '6':
setAnycastCount();
break;
case 'o':
oob=!oob;
System.out.println("oob=" + oob);
break;
case 's':
sync=!sync;
System.out.println("sync=" + sync);
break;
case 'a':
anycasting=!anycasting;
System.out.println("anycasting=" + anycasting);
break;
case 'q':
channel.close();
return;
default:
break;
}
}
}
void invokeRpcs() throws Throwable {
if(anycasting) {
populateAnycastList(channel.getView());
}
else {
if((destination=getReceiver()) == null) {
System.err.println("UnicastTest.invokeRpcs(): receiver is null, cannot send messages");
return;
}
}
num_requests.set(0);
System.out.println("invoking " + num_msgs + " RPCs of " + Util.printBytes(msg_size) + " on " +
(anycasting? anycast_mbrs : destination) + ", sync=" + sync + ", oob=" + oob + ", anycasting=" + anycasting);
// The first call needs to be synchronous with OOB !
RequestOptions options=new RequestOptions(ResponseMode.GET_ALL, 15000, anycasting, null);
if(sync) options.flags(Message.Flag.DONT_BUNDLE);
if(oob) options.flags(Message.Flag.OOB);
options.mode(sync? ResponseMode.GET_ALL : ResponseMode.GET_NONE);
final CountDownLatch latch=new CountDownLatch(1);
Invoker[] invokers=new Invoker[num_threads];
for(int i=0; i < invokers.length; i++) {
if(anycasting)
invokers[i]=new Invoker(anycast_mbrs, options, latch);
else
invokers[i]=new Invoker(destination, options, latch);
invokers[i].setName("invoker-" + i);
invokers[i].start();
}
long start=System.currentTimeMillis();
latch.countDown();
for(Invoker invoker: invokers)
invoker.join();
long time=System.currentTimeMillis() - start;
System.out.println("done invoking " + num_msgs + " in " + destination);
double time_per_req=time / (double)num_msgs;
double reqs_sec=num_msgs / (time / 1000.0);
double throughput=num_msgs * msg_size / (time / 1000.0);
System.out.println(Util.bold("\ninvoked " + num_msgs + " requests in " + time + " ms: " + time_per_req + " ms/req, " +
String.format("%.2f", reqs_sec) + " reqs/sec, " + Util.printBytes(throughput) + "/sec\n"));
}
void setSenderThreads() throws Exception {
int threads=Util.readIntFromStdin("Number of sender threads: ");
int old=this.num_threads;
this.num_threads=threads;
System.out.println("sender threads set to " + num_threads + " (from " + old + ")");
}
void setNumMessages() throws Exception {
num_msgs=Util.readIntFromStdin("Number of RPCs: ");
System.out.println("Set num_msgs=" + num_msgs);
print=num_msgs / 10;
}
void setMessageSize() throws Exception {
msg_size=Util.readIntFromStdin("Message size: ");
System.out.println("set msg_size=" + msg_size);
}
void setAnycastCount() throws Exception {
int tmp=Util.readIntFromStdin("Anycast count: ");
View view=channel.getView();
if(tmp > view.size()) {
System.err.println("anycast count must be smaller or equal to the view size (" + view + ")\n");
return;
}
anycast_count=tmp;
System.out.println("set anycast_count=" + anycast_count);
}
void populateAnycastList(View view) {
if(!anycasting) return;
anycast_mbrs.clear();
List mbrs=view.getMembers();
int index=mbrs.indexOf(local_addr);
for(int i=index + 1; i < index + 1 + anycast_count; i++) {
int new_index=i % mbrs.size();
anycast_mbrs.add(mbrs.get(new_index));
}
System.out.println("local_addr=" + local_addr + ", anycast_mbrs = " + anycast_mbrs);
}
void printView() {
System.out.println("\n-- view: " + channel.getView() + '\n');
try {
System.in.skip(System.in.available());
}
catch(Exception e) {
}
}
private Address getReceiver() {
try {
List mbrs=new ArrayList<>(channel.getView().getMembers());
List site_names=getSites(channel);
for(String site_name: site_names) {
try {
SiteMaster sm=new SiteMaster(site_name);
mbrs.add(sm);
}
catch(Throwable t) {
System.err.println("failed creating site master: " + t);
}
}
System.out.println("pick receiver from the following members:");
int i=0;
for(Address mbr: mbrs) {
if(mbr.equals(channel.getAddress()))
System.out.println("[" + i + "]: " + mbr + " (self)");
else
System.out.println("[" + i + "]: " + mbr);
i++;
}
System.out.flush();
System.in.skip(System.in.available());
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
String str=reader.readLine().trim();
int index=Integer.parseInt(str);
return mbrs.get(index); // index out of bounds caught below
}
catch(Exception e) {
System.err.println("UnicastTest.getReceiver(): " + e);
return null;
}
}
protected static List getSites(JChannel channel) {
RELAY relay=channel.getProtocolStack().findProtocol(RELAY.class);
return relay != null? relay.siteNames() : Collections.emptyList();
}
private class Invoker extends Thread {
private final Address dest;
private final Collection dests;
private final RequestOptions options;
private final CountDownLatch latch;
public Invoker(Address dest, RequestOptions options, CountDownLatch latch) {
this.dest=dest;
this.latch=latch;
this.dests=null;
this.options=options;
}
public Invoker(Collection dests, RequestOptions options, CountDownLatch latch) {
this.latch=latch;
this.dest=null;
this.dests=dests;
this.options=options;
}
public void run() {
byte[] buf=new byte[msg_size];
Object[] args={buf};
MethodCall call=new MethodCall((short)0, args);
try {
latch.await();
}
catch(InterruptedException e) {
e.printStackTrace();
return;
}
for(;;) {
int i=num_requests.incrementAndGet();
if(i > num_msgs)
break;
try {
if(dests != null)
disp.callRemoteMethods(dests, call, options);
else
disp.callRemoteMethod(dest, call, options);
if(print > 0 && i % print == 0)
System.out.println("-- invoked " + i);
}
catch(Throwable throwable) {
throwable.printStackTrace();
}
}
}
}
public static void main(String[] args) {
String props=null;
String name=null;
String cluster_name=null;
for(int i=0; i < args.length; i++) {
if("-props".equals(args[i])) {
props=args[++i];
continue;
}
if("-name".equals(args[i])) {
name=args[++i];
continue;
}
if("-cluster".endsWith(args[i])) {
cluster_name=args[++i];
continue;
}
help();
return;
}
UnicastTestRpc test=null;
try {
test=new UnicastTestRpc();
test.init(props, name, cluster_name);
test.eventLoop();
}
catch(Throwable ex) {
ex.printStackTrace();
if(test != null)
test.stop();
}
}
static void help() {
System.out.println("UnicastTestRpc [-help] [-props ] [-name name] [-cluster name]");
}
}