use of org.eclipse.californium.unixhealth.NetStatLogger in project californium by eclipse.
the class ExtendedTestServer method main.
public static void main(String[] args) {
CommandLine cmd = new CommandLine(config);
config.register(cmd);
try {
ParseResult result = cmd.parseArgs(args);
if (result.isVersionHelpRequested()) {
System.out.println("\nCalifornium (Cf) " + cmd.getCommandName() + " " + PlugtestServer.CALIFORNIUM_BUILD_VERSION);
cmd.printVersionHelp(System.out);
System.out.println();
}
if (result.isUsageHelpRequested()) {
cmd.usage(System.out);
return;
}
} catch (ParameterException ex) {
System.err.println(ex.getMessage());
System.err.println();
cmd.usage(System.err);
System.exit(-1);
}
STATISTIC_LOGGER.error("start!");
ManagementStatistic management = new ManagementStatistic(STATISTIC_LOGGER);
try {
K8sManagementClient k8sClient = null;
K8sDiscoverClient k8sGroup = null;
DtlsClusterConnectorConfig.Builder clusterConfigBuilder = DtlsClusterConnectorConfig.builder();
Configuration configuration = Configuration.createWithFile(CONFIG_FILE, CONFIG_HEADER, DEFAULTS);
if (config.cluster != null) {
int nodeId = -1;
clusterConfigBuilder.setBackwardMessage(config.cluster.backwardClusterMessages);
if (config.cluster.clusterType.k8sCluster != null) {
clusterConfigBuilder.setAddress(config.cluster.clusterType.k8sCluster.cluster);
clusterConfigBuilder.setClusterMac(config.cluster.dtlsClusterMac);
K8sDiscoverClient.setConfiguration(clusterConfigBuilder);
k8sClient = new K8sManagementJdkClient();
k8sGroup = new K8sDiscoverClient(k8sClient, config.cluster.clusterType.k8sCluster.externalPort);
nodeId = k8sGroup.getNodeID();
LOGGER.info("dynamic k8s-cluster!");
} else if (config.cluster.clusterType.simpleCluster != null) {
for (ClusterNode cluster : config.cluster.clusterType.simpleCluster.dtlsClusterNodes) {
if (cluster.dtls != null) {
nodeId = cluster.nodeId;
break;
}
}
if (nodeId < 0) {
throw new IllegalArgumentException("at least one cluster node must have a dtls interface!");
}
if (config.cluster.clusterType.simpleCluster.dtlsClusterGroup != null) {
LOGGER.info("dynamic dtls-cluster!");
String secret = config.cluster.clusterType.simpleCluster.dtlsClusterGroupSecurity;
if (secret != null) {
SecretKey key = SecretUtil.create(secret.getBytes(), "PSK");
clusterConfigBuilder.setSecure("dtls-mgmt", key);
SecretUtil.destroy(key);
clusterConfigBuilder.setClusterMac(config.cluster.dtlsClusterMac);
}
} else {
LOGGER.info("static dtls-cluster!");
}
}
configuration.set(DtlsConfig.DTLS_CONNECTION_ID_NODE_ID, nodeId);
} else if (config.plugtest) {
// start standard plugtest server
PlugtestServer.init(config);
}
Configuration udpConfiguration = new Configuration(configuration).set(CoapConfig.MAX_MESSAGE_SIZE, configuration.get(EXTERNAL_UDP_MAX_MESSAGE_SIZE)).set(CoapConfig.PREFERRED_BLOCK_SIZE, configuration.get(EXTERNAL_UDP_PREFERRED_BLOCK_SIZE));
Map<Select, Configuration> protocolConfig = new HashMap<>();
protocolConfig.put(new Select(Protocol.UDP, InterfaceType.EXTERNAL), udpConfiguration);
// create server
List<Protocol> protocols = config.getProtocols();
List<InterfaceType> types = config.getInterfaceTypes();
ScheduledExecutorService executor = //
ExecutorsUtil.newScheduledThreadPool(//
configuration.get(CoapConfig.PROTOCOL_STAGE_THREAD_COUNT), // $NON-NLS-1$
new NamedThreadFactory("ExtCoapServer(main)#"));
ScheduledExecutorService secondaryExecutor = ExecutorsUtil.newDefaultSecondaryScheduler("ExtCoapServer(secondary)#");
long notifyIntervalMillis = config.getNotifyIntervalMillis();
final ExtendedTestServer server = new ExtendedTestServer(configuration, protocolConfig, config.benchmark, notifyIntervalMillis);
server.setVersion(PlugtestServer.CALIFORNIUM_BUILD_VERSION);
server.setTag("EXTENDED-TEST");
server.setExecutors(executor, secondaryExecutor, false);
server.add(new Echo(configuration.get(CoapConfig.MAX_RESOURCE_BODY_SIZE), config.echoDelay ? executor : null));
if (config.diagnose) {
server.add(new Diagnose(server));
}
server.add(new ReverseRequest(configuration, executor));
ReverseObserve reverseObserver = new ReverseObserve(configuration, executor);
server.add(reverseObserver);
if (k8sGroup != null) {
DtlsClusterConnectorConfig clusterConfig = clusterConfigBuilder.build();
server.addClusterEndpoint(secondaryExecutor, config.cluster.clusterType.k8sCluster.dtls, k8sGroup.getNodeID(), clusterConfig, null, k8sGroup, config);
} else if (config.cluster != null && config.cluster.clusterType.simpleCluster != null) {
ClusterGroup group = null;
DtlsClusterConnector.ClusterNodesProvider nodes = null;
if (config.cluster.clusterType.simpleCluster.dtlsClusterGroup == null) {
nodes = new DtlsClusterConnector.ClusterNodesProvider() {
@Override
public InetSocketAddress getClusterNode(int nodeId) {
for (ClusterNode node : config.cluster.clusterType.simpleCluster.dtlsClusterNodes) {
if (node.nodeId == nodeId) {
return node.cluster;
}
}
return null;
}
@Override
public boolean available(InetSocketAddress destinationConnector) {
return true;
}
};
}
for (ClusterNode cluster : config.cluster.clusterType.simpleCluster.dtlsClusterNodes) {
if (cluster.dtls != null) {
DtlsClusterConnectorConfig clusterConfig = DtlsClusterConnectorConfig.builder(clusterConfigBuilder.getIncompleteConfig()).setAddress(cluster.cluster).build();
if (config.cluster.clusterType.simpleCluster.dtlsClusterGroup != null) {
group = new ClusterGroup(config.cluster.clusterType.simpleCluster.dtlsClusterGroup);
}
server.addClusterEndpoint(secondaryExecutor, cluster.dtls, cluster.nodeId, clusterConfig, nodes, group, config);
}
}
} else if (config.restore != null) {
// restore the dtls state from an other host with different
// local network addresses,
// requires to use the wildcard address for the connector.
int port = configuration.get(CoapConfig.COAP_SECURE_PORT);
server.addEndpoint(new InetSocketAddress(port), config);
}
// Statistic for dropped udp messages
final NetSocketHealthLogger socketLogger = new NetSocketHealthLogger("udp");
EndpointNetSocketObserver socketObserver = null;
long interval = configuration.get(SystemConfig.HEALTH_STATUS_INTERVAL, TimeUnit.MILLISECONDS);
if (interval > 0 && socketLogger.isEnabled()) {
server.add(socketLogger);
long readInterval = configuration.get(UDP_DROPS_READ_INTERVAL, TimeUnit.MILLISECONDS);
if (interval > readInterval) {
secondaryExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
socketLogger.read();
}
}, readInterval, readInterval, TimeUnit.MILLISECONDS);
}
socketObserver = new EndpointNetSocketObserver(socketLogger);
server.addDefaultEndpointObserver(socketObserver);
EndpointNetSocketObserver internalSocketObserver = new EndpointNetSocketObserver(socketLogger) {
protected SimpleCounterStatistic getExternalStatistic(Endpoint endpoint) {
CounterStatisticManager dtlsStatisticManager = getDtlsStatisticManager(endpoint);
return dtlsStatisticManager != null ? dtlsStatisticManager.getByKey(DtlsClusterHealthLogger.DROPPED_INTERNAL_UDP_MESSAGES) : null;
}
@Override
protected InetSocketAddress getAddress(Endpoint endpoint) {
if (endpoint instanceof CoapEndpoint) {
Connector connector = ((CoapEndpoint) endpoint).getConnector();
if (connector instanceof DtlsClusterConnector) {
return ((DtlsClusterConnector) connector).getClusterInternalAddress();
}
}
return null;
}
};
server.addDefaultEndpointObserver(internalSocketObserver);
}
// using cluster removes dtls from protocols
server.addEndpoints(config.interfacePatterns, types, protocols, config);
if (server.getEndpoints().isEmpty()) {
System.err.println("no endpoint available!");
System.exit(PlugtestServer.ERR_INIT_FAILED);
}
for (Endpoint ep : server.getEndpoints()) {
ep.addNotificationListener(reverseObserver);
}
InetSocketAddress httpLocal = config.k8sMonitor;
InetSocketAddress httpsRestoreLocal = null;
InetSocketAddress httpsRestoreOther = null;
SSLContext context = null;
K8sRestoreJdkHttpClient client = null;
SSLContext clientContext = null;
if (config.restore != null) {
if (config.restore.restoreSource.restoreK8s != null) {
httpsRestoreLocal = config.restore.restoreSource.restoreK8s;
httpsRestoreOther = new InetSocketAddress(httpsRestoreLocal.getPort());
} else if (config.restore.restoreSource.restorePair != null) {
httpsRestoreLocal = config.restore.restoreSource.restorePair.restoreLocal;
httpsRestoreOther = config.restore.restoreSource.restorePair.restoreOther;
}
context = CredentialsUtil.getClusterInternalHttpsServerContext();
}
if (httpLocal != null || httpsRestoreLocal != null) {
long maxAgeSeconds = config.restore != null ? TimeUnit.HOURS.toSeconds(config.restore.maxAge) : 0;
final JdkMonitorService monitor = new JdkMonitorService(httpLocal, httpsRestoreLocal, maxAgeSeconds, context);
monitor.addServer(server);
if (context != null) {
clientContext = CredentialsUtil.getClusterInternalHttpsClientContext();
if (clientContext != null) {
client = new K8sRestoreJdkHttpClient();
monitor.addComponent(client);
}
}
monitor.start();
}
PlugtestServer.add(server);
PlugtestServer.load(config);
// start standard plugtest server and shutdown
PlugtestServer.start(executor, secondaryExecutor, config, configuration, socketObserver, null);
server.start();
server.addLogger(!config.benchmark);
List<CounterStatisticManager> statistics = new ArrayList<>();
ObserveStatisticLogger obsStatLogger = new ObserveStatisticLogger(server.getTag());
if (obsStatLogger.isEnabled()) {
statistics.add(obsStatLogger);
server.add(obsStatLogger);
server.setObserveHealth(obsStatLogger);
}
Resource child = server.getRoot().getChild(Diagnose.RESOURCE_NAME);
if (child instanceof Diagnose) {
((Diagnose) child).update(statistics);
}
PlugtestServer.ActiveInputReader reader = new PlugtestServer.ActiveInputReader();
if (interval > 0) {
if (config.ipv4) {
NetStatLogger netStatLogger = new NetStatLogger("udp", false);
if (netStatLogger.isEnabled()) {
server.add(netStatLogger);
LOGGER.info("udp health enabled.");
} else {
LOGGER.warn("udp health not enabled!");
}
}
if (config.ipv6) {
NetStatLogger netStatLogger = new NetStatLogger("udp6", true);
if (netStatLogger.isEnabled()) {
server.add(netStatLogger);
LOGGER.info("udp6 health enabled.");
} else {
LOGGER.warn("udp6 health not enabled!");
}
}
} else {
interval = 30000;
}
Runtime runtime = Runtime.getRuntime();
long max = runtime.maxMemory();
StringBuilder builder = new StringBuilder(ExtendedTestServer.class.getSimpleName());
if (!PlugtestServer.CALIFORNIUM_BUILD_VERSION.isEmpty()) {
builder.append(", version ").append(PlugtestServer.CALIFORNIUM_BUILD_VERSION);
}
builder.append(", ").append(max / (1024 * 1024)).append("MB heap, started ...");
LOGGER.info("{}", builder);
while (!server.isReady()) {
Thread.sleep(500);
}
if (httpsRestoreOther != null && client != null) {
if (config.restore.restoreSource.restoreK8s != null) {
if (k8sClient == null) {
k8sClient = new K8sManagementJdkClient();
}
if (k8sGroup != null) {
client.restoreCluster(k8sClient, httpsRestoreOther.getPort(), clientContext, server);
} else {
client.restoreSingle(k8sClient, httpsRestoreOther.getPort(), clientContext, server);
}
} else {
String host = StringUtil.toHostString(httpsRestoreOther);
client.restore(InetAddress.getLocalHost().getHostName(), host, httpsRestoreOther.getPort(), clientContext, server);
}
}
if (!config.benchmark) {
LOGGER.info("{} without benchmark started ...", ExtendedTestServer.class.getSimpleName());
for (; ; ) {
if (PlugtestServer.console(reader, interval)) {
break;
}
server.dump();
}
} else {
long inputTimeout = interval < 15000 ? interval : 15000;
long lastGcCount = 0;
long lastDumpNanos = ClockUtil.nanoRealtime();
for (; ; ) {
if (PlugtestServer.console(reader, inputTimeout)) {
break;
}
if (management.useWarningMemoryUsage()) {
long used = runtime.totalMemory() - runtime.freeMemory();
int fill = (int) ((used * 100L) / max);
if (fill > 80) {
LOGGER.info("Maxium heap size: {}M {}% used.", max / MEGA, fill);
LOGGER.info("Heap may exceed! Enlarge the maxium heap size.");
LOGGER.info("Or consider to reduce the value of " + CoapConfig.EXCHANGE_LIFETIME);
LOGGER.info("in \"{}\" or set", CONFIG_FILE);
LOGGER.info("{} to {} or", CoapConfig.DEDUPLICATOR, CoapConfig.NO_DEDUPLICATOR);
LOGGER.info("{} in that file.", CoapConfig.PEERS_MARK_AND_SWEEP_MESSAGES);
}
}
long gcCount = management.getCollectionCount();
if (lastGcCount < gcCount) {
management.printManagementStatistic();
lastGcCount = gcCount;
long clones = DatagramWriter.COPIES.get();
long takes = DatagramWriter.TAKES.get();
if (clones + takes > 0) {
STATISTIC_LOGGER.info("DatagramWriter {} clones, {} takes, {}%", clones, takes, (takes * 100L) / (takes + clones));
}
}
long now = ClockUtil.nanoRealtime();
if ((now - lastDumpNanos - TimeUnit.MILLISECONDS.toNanos(interval)) > 0) {
lastDumpNanos = now;
server.dump();
}
}
}
PlugtestServer.shutdown();
server.stop();
LOGGER.info("Executor shutdown ...");
ExecutorsUtil.shutdownExecutorGracefully(500, executor, secondaryExecutor);
PlugtestServer.exit();
LOGGER.info("Exit ...");
} catch (Exception e) {
System.err.printf("Failed to create " + ExtendedTestServer.class.getSimpleName() + ": %s\n", e.getMessage());
e.printStackTrace(System.err);
System.err.println("Exiting");
System.exit(PlugtestServer.ERR_INIT_FAILED);
}
}
use of org.eclipse.californium.unixhealth.NetStatLogger in project californium by eclipse.
the class ExampleCrossProxy2 method main.
public static void main(String[] args) throws IOException {
Configuration proxyConfig = Configuration.createWithFile(CONFIG_FILE, CONFIG_HEADER, DEFAULTS);
ExampleCrossProxy2 proxy = new ExampleCrossProxy2(proxyConfig, false, true);
ExampleHttpServer httpServer = null;
Configuration config = ExampleCoapServer.init();
for (int index = 0; index < args.length; ++index) {
Integer port = parse(args[index], "coap", ExampleCoapServer.DEFAULT_COAP_PORT, config, CoapConfig.COAP_PORT);
if (port != null) {
new ExampleCoapServer(config, port);
// reverse proxy: add a proxy resource with a translator
// returning a fixed destination URI
// don't add this to the ProxyMessageDeliverer
URI destination = URI.create("coap://localhost:" + port + "/coap-target");
ProxyCoapResource reverseProxy = ProxyCoapResource.createReverseProxy("destination1", true, true, true, destination, proxy.endpoints);
reverseProxy.setCache(proxy.cache);
proxy.coapProxyServer.getRoot().getChild("targets").add(reverseProxy);
System.out.println("CoAP Proxy at: coap://localhost:" + proxy.coapPort + "/coap2coap and demo-server at coap://localhost:" + port + ExampleCoapServer.RESOURCE);
System.out.println("HTTP Proxy at: http://localhost:" + proxy.httpPort + "/proxy/coap://localhost:" + port + ExampleCoapServer.RESOURCE);
} else {
port = parse(args[index], "http", ExampleHttpServer.DEFAULT_PORT, null, null);
if (port != null) {
httpServer = new ExampleHttpServer(config, port);
// reverse proxy: add a proxy resource with a translator
// returning a fixed destination URI
// don't add this to the ProxyMessageDeliverer
URI destination = URI.create("http://localhost:" + port + "/http-target");
ProxyCoapResource reverseProxy = ProxyCoapResource.createReverseProxy("destination2", true, true, true, destination, proxy.endpoints);
reverseProxy.setCache(proxy.cache);
proxy.coapProxyServer.getRoot().getChild("targets").add(reverseProxy);
System.out.println("CoAP Proxy at: coap://localhost:" + proxy.coapPort + "/coap2http and demo server at http://localhost:" + port + ExampleHttpServer.RESOURCE);
}
}
}
startManagamentStatistic();
Runtime runtime = Runtime.getRuntime();
long max = runtime.maxMemory();
System.out.println(ExampleCrossProxy2.class.getSimpleName() + " started (" + max / (1024 * 1024) + "MB heap) ...");
long lastGcCount = 0;
NetStatLogger netstat = new NetStatLogger("udp", false);
for (; ; ) {
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
break;
}
long used = runtime.totalMemory() - runtime.freeMemory();
int fill = (int) ((used * 100L) / max);
if (fill > 80) {
System.out.println("Maxium heap size: " + max / (1024 * 1024) + "M " + fill + "% used.");
System.out.println("Heap may exceed! Enlarge the maxium heap size.");
System.out.println("Or consider to reduce the value of " + CoapConfig.EXCHANGE_LIFETIME);
System.out.println("in \"" + CONFIG_FILE + "\" or set");
System.out.println(CoapConfig.DEDUPLICATOR + " to " + CoapConfig.NO_DEDUPLICATOR + " there.");
break;
}
long gcCount = 0;
for (GarbageCollectorMXBean gcMXBean : ManagementFactory.getGarbageCollectorMXBeans()) {
long count = gcMXBean.getCollectionCount();
if (0 < count) {
gcCount += count;
}
}
if (lastGcCount < gcCount) {
printManagamentStatistic();
lastGcCount = gcCount;
netstat.dump();
if (httpServer != null) {
httpServer.dumpStatistic();
}
}
}
}
use of org.eclipse.californium.unixhealth.NetStatLogger in project californium by eclipse.
the class ExampleSecureProxy2 method main.
public static void main(String[] args) throws IOException, GeneralSecurityException {
Configuration proxyConfig = Configuration.createWithFile(CONFIG_FILE, CONFIG_HEADER, DEFAULTS);
ExampleSecureProxy2 proxy = new ExampleSecureProxy2(proxyConfig);
Configuration config = ExampleCoapServer.init();
for (int index = 0; index < args.length; ++index) {
Integer port = parse(args[index], "coaps", ExampleCoapServer.DEFAULT_COAP_SECURE_PORT, config, CoapConfig.COAP_SECURE_PORT);
if (port != null) {
DtlsConnectorConfig.Builder builder = SecureEndpointPool.setupServer(config);
builder.setAddress(new InetSocketAddress(port));
DTLSConnector connector = new DTLSConnector(builder.build());
CoapEndpoint endpoint = CoapEndpoint.builder().setConfiguration(config).setConnector(connector).build();
new ExampleCoapServer(endpoint);
// reverse proxy: add a proxy resource with a translator
// returning a fixed destination URI
// don't add this to the ProxyMessageDeliverer
URI destination = URI.create("coaps://localhost:" + port + "/coap-target");
CoapResource reverseProxy = ProxyCoapResource.createReverseProxy("destination1", true, true, true, destination, proxy.pool);
proxy.coapProxyServer.getRoot().getChild("targets").add(reverseProxy);
System.out.println("CoAP Proxy at: coap://localhost:" + proxy.coapPort + "/coap2coap and demo-server at coaps://localhost:" + port + ExampleCoapServer.RESOURCE);
}
}
startManagamentStatistic();
Runtime runtime = Runtime.getRuntime();
long max = runtime.maxMemory();
System.out.println(ExampleSecureProxy2.class.getSimpleName() + " started (" + max / (1024 * 1024) + "MB heap) ...");
long lastGcCount = 0;
NetStatLogger netstat = new NetStatLogger("udp", false);
for (; ; ) {
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
break;
}
long used = runtime.totalMemory() - runtime.freeMemory();
int fill = (int) ((used * 100L) / max);
if (fill > 80) {
System.out.println("Maxium heap size: " + max / (1024 * 1024) + "M " + fill + "% used.");
System.out.println("Heap may exceed! Enlarge the maxium heap size.");
System.out.println("Or consider to reduce the value of " + CoapConfig.EXCHANGE_LIFETIME);
System.out.println("in \"" + CONFIG_FILE + "\" or set");
System.out.println(CoapConfig.DEDUPLICATOR + " to " + CoapConfig.NO_DEDUPLICATOR + " there.");
}
long gcCount = 0;
for (GarbageCollectorMXBean gcMXBean : ManagementFactory.getGarbageCollectorMXBeans()) {
long count = gcMXBean.getCollectionCount();
if (0 < count) {
gcCount += count;
}
}
if (lastGcCount < gcCount) {
printManagamentStatistic();
lastGcCount = gcCount;
netstat.dump();
}
}
}
use of org.eclipse.californium.unixhealth.NetStatLogger in project californium by eclipse.
the class PlugtestServer method start.
public static void start(ScheduledExecutorService mainExecutor, ScheduledExecutorService secondaryExecutor, BaseConfig config, Configuration configuration, EndpointNetSocketObserver observer, ActiveInputReader inputReader) {
if (server != null) {
server.setExecutors(mainExecutor, secondaryExecutor, true);
if (observer != null) {
server.addDefaultEndpointObserver(observer);
}
server.add(new Echo(configuration.get(CoapConfig.MAX_RESOURCE_BODY_SIZE), config.echoDelay ? mainExecutor : null));
server.start();
server.addLogger(true);
LOGGER.info("{} started ...", PlugtestServer.class.getSimpleName());
if (inputReader != null) {
long interval = configuration.get(SystemConfig.HEALTH_STATUS_INTERVAL, TimeUnit.MILLISECONDS);
if (interval > 0) {
if (observer != null) {
server.add(observer.getNetSocketHealth());
}
if (config.ipv4) {
server.add(new NetStatLogger("udp", false));
}
if (config.ipv6) {
server.add(new NetStatLogger("udp6", true));
}
} else {
interval = 30000;
}
for (; ; ) {
if (console(inputReader, interval)) {
break;
}
server.dump();
}
LOGGER.info("{} stopping ...", PlugtestServer.class.getSimpleName());
shutdown();
}
}
}
use of org.eclipse.californium.unixhealth.NetStatLogger in project californium by eclipse.
the class BenchmarkClient method main.
public static void main(String[] args) throws InterruptedException, IOException {
TcpConfig.register();
BenchmarkClient.args = args;
startManagamentStatistic();
config.configurationHeader = CONFIG_HEADER;
config.customConfigurationDefaultsProvider = DEFAULTS;
config.configurationFile = CONFIG_FILE;
ClientInitializer.init(args, config, false);
if (config.helpRequested) {
System.exit(0);
}
// random part of PSK identity
final SecureRandom random = new SecureRandom();
final byte[] id = new byte[8];
final int clients = config.clients;
BenchmarkClient.clients = clients;
int reverseResponses = 0;
int notifies = 0;
if (config.blockwiseOptions != null) {
if (config.blockwiseOptions.bertBlocks != null && config.blockwiseOptions.bertBlocks > 0) {
config.configuration.set(CoapConfig.MAX_MESSAGE_SIZE, 1024);
config.configuration.set(CoapConfig.PREFERRED_BLOCK_SIZE, 1024);
config.configuration.set(CoapConfig.TCP_NUMBER_OF_BULK_BLOCKS, config.blockwiseOptions.bertBlocks);
} else if (config.blockwiseOptions.blocksize != null) {
config.configuration.set(CoapConfig.MAX_MESSAGE_SIZE, config.blockwiseOptions.blocksize);
config.configuration.set(CoapConfig.PREFERRED_BLOCK_SIZE, config.blockwiseOptions.blocksize);
}
}
if (config.reverse != null) {
reverseResponses = config.reverse.responses;
}
if (config.observe != null) {
notifies = config.observe.notifies;
}
if (config.timeout != null) {
config.configuration.set(CoapConfig.NON_LIFETIME, config.timeout, TimeUnit.MILLISECONDS);
}
offload = config.configuration.get(CoapConfig.USE_MESSAGE_OFFLOADING);
URI tempUri;
try {
tempUri = new URI(config.uri);
} catch (URISyntaxException e) {
tempUri = null;
System.err.println("Invalid URI: " + e.getMessage());
System.exit(-1);
}
final URI uri = tempUri;
overallRequests = (config.requests * clients);
overallReverseResponses = (reverseResponses * clients);
overallNotifies = (notifies * clients);
if (overallRequests < 0) {
// overflow
overallRequests = Integer.MAX_VALUE;
}
if (overallReverseResponses < 0) {
// overflow
overallReverseResponses = Integer.MAX_VALUE;
}
if (overallNotifies < 0) {
// overflow
overallNotifies = Integer.MAX_VALUE;
}
overallRequestsDownCounter.set(overallRequests);
overallResponsesDownCounter.set(overallRequests);
overallReverseResponsesDownCounter.set(overallReverseResponses);
overallNotifiesDownCounter.set(overallNotifies);
final List<BenchmarkClient> clientList = Collections.synchronizedList(new ArrayList<BenchmarkClient>(clients));
ScheduledExecutorService executor = ExecutorsUtil.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new DaemonThreadFactory("Aux#"));
final ScheduledExecutorService connectorExecutor = config.configuration.get(BENCHMARK_CLIENT_THREADS) == 0 ? executor : null;
final boolean secure = CoAP.isSecureScheme(uri.getScheme());
final boolean dtls = secure && !CoAP.isTcpScheme(uri.getScheme());
final ScheduledThreadPoolExecutor secondaryExecutor = new ScheduledThreadPoolExecutor(2, new DaemonThreadFactory("Aux(secondary)#"));
String proxyMessage = "";
if (config.proxy != null) {
proxyMessage = "via proxy " + config.proxy + " ";
}
System.out.format("Create %d %s%sbenchmark clients, expect to send %d requests overall %sto %s%n", clients, !config.stop ? "none-stop " : "", secure ? "secure " : "", overallRequests, proxyMessage, uri);
if (overallReverseResponses > 0) {
if (config.reverse.min.equals(config.reverse.max)) {
System.out.format("Expect %d notifies sent, interval %d [ms]%n", overallReverseResponses, config.reverse.min);
} else {
System.out.format("Expect %d notifies sent, interval %d ... %d [ms]%n", overallReverseResponses, config.reverse.min, config.reverse.max);
}
}
if (overallNotifies > 0) {
System.out.format("Expect %d notifies received, reregister every %d and register every %d notify%n", overallNotifies, config.observe.reregister, config.observe.register);
}
initialConnectDownCounter.set(clients);
final boolean psk = config.authenticationModes.contains(AuthenticationMode.PSK) || config.authenticationModes.contains(AuthenticationMode.ECDHE_PSK);
final boolean rpk = config.authenticationModes.contains(AuthenticationMode.RPK);
long startupNanos = System.nanoTime();
final AuthenticationMode authentication = config.authenticationModes.isEmpty() ? null : config.authenticationModes.get(0);
final CountDownLatch start = new CountDownLatch(clients);
if (secure && authentication != null) {
switch(authentication) {
case NONE:
System.out.println("No authentication.");
break;
case PSK:
System.out.println("Use PSK.");
break;
case RPK:
System.out.println("Use RPK.");
break;
case X509:
System.out.println("Use X509.");
break;
case ECDHE_PSK:
System.out.println("Use PSK/ECDHE.");
break;
}
}
final ThreadLocalKeyPairGenerator keyPairGenerator = rpk ? createKeyPairGenerator() : null;
// Create & start clients
final AtomicBoolean errors = new AtomicBoolean();
health = new HealthStatisticLogger(uri.getScheme(), CoAP.isUdpScheme(uri.getScheme()));
if (CoAP.isUdpScheme(uri.getScheme())) {
netstat4 = new NetStatLogger("udp4", false);
netstat6 = new NetStatLogger("udp6", true);
}
final String tag = config.tag == null ? "client-" : config.tag;
final int pskOffset = config.pskIndex != null ? config.pskIndex : 0;
for (int index = 0; index < clients; ++index) {
final int currentIndex = index;
final String identity;
final byte[] secret;
if (secure && psk) {
if (config.pskStore != null) {
int pskIndex = (pskOffset + index) % config.pskStore.size();
identity = config.pskStore.getIdentity(pskIndex);
secret = config.pskStore.getSecrets(pskIndex);
} else if (index == 0) {
identity = config.identity;
secret = config.secretKey;
} else {
random.nextBytes(id);
identity = ConnectorConfig.PSK_IDENTITY_PREFIX + StringUtil.byteArray2Hex(id);
secret = config.secretKey;
}
} else {
identity = null;
secret = null;
}
Runnable run = new Runnable() {
@Override
public void run() {
if (errors.get()) {
return;
}
ClientConfig connectionConfig = config;
if (secure) {
if (rpk) {
if (keyPairGenerator != null) {
try {
KeyPairGenerator generator = keyPairGenerator.current();
generator.initialize(new ECGenParameterSpec("secp256r1"), RandomManager.currentSecureRandom());
KeyPair keyPair = generator.generateKeyPair();
connectionConfig = connectionConfig.create(keyPair.getPrivate(), keyPair.getPublic());
} catch (GeneralSecurityException ex) {
if (!errors.getAndSet(true)) {
ex.printStackTrace();
System.out.format("Failed after %d clients, exit Benchmark.%n", (clients - start.getCount()));
System.exit(-1);
}
}
}
}
if (psk) {
connectionConfig = connectionConfig.create(identity, secret);
}
}
if (connectionConfig == config) {
connectionConfig = config.create();
}
connectionConfig.tag = tag + currentIndex;
CoapEndpoint coapEndpoint = ClientInitializer.createEndpoint(connectionConfig, connectorExecutor);
if (health.isEnabled()) {
coapEndpoint.addPostProcessInterceptor(health);
}
BenchmarkClient client = new BenchmarkClient(currentIndex, config.reverse, uri, coapEndpoint, connectorExecutor, secondaryExecutor);
clientList.add(client);
try {
client.start();
start.countDown();
if (currentIndex == 0) {
// first client, so test request
if (client.test()) {
System.out.println("Benchmark clients, first request successful.");
} else {
System.out.format("Request %s POST failed, exit Benchmark.%n", uri);
System.exit(-1);
}
// ensure to use ephemeral port for other clients
config.localPort = null;
}
} catch (RuntimeException e) {
if (!errors.getAndSet(true)) {
e.printStackTrace();
System.out.format("Failed after %d clients, exit Benchmark.%n", (clients - start.getCount()));
System.exit(-1);
}
}
}
};
if (index == 0) {
// first client, so test request
if (identity != null) {
// first client, so test request
if (secret == null) {
System.out.println("ID: " + identity);
} else {
System.out.println("ID: " + identity + ", " + new String(secret));
}
}
run.run();
} else if (!errors.get()) {
startupNanos = System.nanoTime();
executor.execute(run);
}
}
start.await();
startupNanos = System.nanoTime() - startupNanos;
if (clients == 1) {
System.out.format("Benchmark client created. %s%n", formatTime(startupNanos));
} else {
System.out.format("Benchmark clients created. %s%s%n", formatTime(startupNanos), formatPerSecond("clients", clients - 1, startupNanos));
}
// Start Test
boolean stale = false;
startRequestNanos = System.nanoTime();
startReverseResponseNanos = startRequestNanos;
startNotifiesNanos = startRequestNanos;
long lastRequestsCountDown = overallRequestsDownCounter.get();
long lastResponsesCountDown = overallResponsesDownCounter.get();
long lastTransmissions = transmissionCounter.get();
long lastRetransmissions = retransmissionCounter.get();
long lastTransmissionErrrors = transmissionErrorCounter.get();
int lastUnavailable = overallServiceUnavailable.get();
int lastHonoCmds = overallHonoCmds.get();
int requestsPerClient = config.requests <= 10 ? config.requests : -1;
for (int index = clients - 1; index >= 0; --index) {
BenchmarkClient client = clientList.get(index);
if (index == 0) {
--requestsPerClient;
}
client.startBenchmark(requestsPerClient);
}
registerShutdown();
System.out.println("Benchmark started.");
long staleTime = System.nanoTime();
long interval = config.interval == null ? 0 : TimeUnit.MILLISECONDS.toNanos(config.interval);
if (dtls) {
interval = Math.max(interval, DTLS_TIMEOUT_NANOS);
}
long staleTimeout = DEFAULT_TIMEOUT_NANOS + interval;
int count = 0;
// Wait with timeout or all requests send.
while (!overallRequestsDone.await(DEFAULT_TIMEOUT_NANOS, TimeUnit.NANOSECONDS)) {
long currentRequestsCountDown = overallRequestsDownCounter.get();
long currentResponsesCountDown = overallResponsesDownCounter.get();
int numberOfClients = clientCounter.get();
int connectsPending = initialConnectDownCounter.get();
long requestsDifference = (lastRequestsCountDown - currentRequestsCountDown);
long responsesDifference = (lastResponsesCountDown - currentResponsesCountDown);
long currentOverallSentRequests = overallRequests - currentRequestsCountDown;
if ((responsesDifference == 0 && currentResponsesCountDown < overallRequests) || (numberOfClients == 0)) {
// no new requests, clients are stale, or no clients left
// adjust start time with timeout
long timeout = System.nanoTime() - staleTime;
if ((timeout - staleTimeout) > 0) {
startRequestNanos += timeout;
startReverseResponseNanos = startRequestNanos;
startNotifiesNanos = startRequestNanos;
stale = true;
System.out.format("[%04d]: %d requests, stale (%d clients, %d pending)%n", ++count, currentOverallSentRequests, numberOfClients, connectsPending);
break;
}
} else {
staleTime = System.nanoTime();
}
long transmissions = transmissionCounter.get();
long transmissionsDifference = transmissions - lastTransmissions;
long retransmissions = retransmissionCounter.get();
long retransmissionsDifference = retransmissions - lastRetransmissions;
long transmissionErrors = transmissionErrorCounter.get();
long transmissionErrorsDifference = transmissionErrors - lastTransmissionErrrors;
int unavailable = overallServiceUnavailable.get();
int unavailableDifference = unavailable - lastUnavailable;
int honoCmds = overallHonoCmds.get();
int honoCmdsDifference = honoCmds - lastHonoCmds;
lastRequestsCountDown = currentRequestsCountDown;
lastResponsesCountDown = currentResponsesCountDown;
lastTransmissions = transmissions;
lastRetransmissions = retransmissions;
lastTransmissionErrrors = transmissionErrors;
lastUnavailable = unavailable;
lastHonoCmds = honoCmds;
StringBuilder line = new StringBuilder();
line.append(String.format("[%04d]: ", ++count));
line.append(String.format("%d requests (%d reqs/s", currentOverallSentRequests, roundDiv(responsesDifference, DEFAULT_TIMEOUT_SECONDS)));
line.append(", ").append(formatRetransmissions(retransmissionsDifference, transmissionsDifference, responsesDifference));
line.append(", ").append(formatTransmissionErrors(transmissionErrorsDifference, requestsDifference, responsesDifference));
if (unavailable > 0) {
line.append(", ").append(formatUnavailable(unavailableDifference, responsesDifference));
}
if (honoCmds > 0) {
line.append(", ").append(formatHonoCmds(honoCmdsDifference, responsesDifference));
}
line.append(String.format(", %d clients", numberOfClients));
if (connectsPending > 0) {
line.append(String.format(", %d pending", connectsPending));
}
line.append(")");
System.out.println(line);
}
timeRequestNanos = System.nanoTime() - startRequestNanos;
boolean observe = false;
long lastReverseResponsesCountDown = overallReverseResponsesDownCounter.get();
if (config.reverse != null && lastReverseResponsesCountDown > 0) {
System.out.println("Requests send.");
long lastChangeNanoRealtime = ClockUtil.nanoRealtime();
while (!overallReveresResponsesDone.await(DEFAULT_TIMEOUT_NANOS, TimeUnit.NANOSECONDS)) {
long currentReverseResponsesCountDown = overallReverseResponsesDownCounter.get();
int numberOfClients = clientCounter.get();
int observers = overallObserverCounter.get();
long reverseResponsesDifference = (lastReverseResponsesCountDown - currentReverseResponsesCountDown);
long currentOverallReverseResponses = overallReverseResponses - currentReverseResponsesCountDown;
if (overallObservationRegistrationCounter.get() > 0) {
observe = true;
}
long time = 0;
if (currentReverseResponsesCountDown < overallReverseResponses) {
if (reverseResponsesDifference == 0) {
time = ClockUtil.nanoRealtime() - lastChangeNanoRealtime;
} else {
lastChangeNanoRealtime = ClockUtil.nanoRealtime();
}
} else {
// wait extra DEFAULT_TIMEOUT_NANOS for start of reverse
// responses.
time = ClockUtil.nanoRealtime() - lastChangeNanoRealtime - DEFAULT_TIMEOUT_NANOS;
}
if (config.reverse.max < TimeUnit.NANOSECONDS.toMillis(time - DEFAULT_TIMEOUT_NANOS) || (numberOfClients == 0)) {
// no new notifies for interval max, clients are stale, or
// no clients left
// adjust start time with timeout
startReverseResponseNanos += time;
stale = true;
if (observe) {
System.out.format("[%04d]: %d notifies, stale (%d clients, %d observes)%n", ++count, currentOverallReverseResponses, numberOfClients, observers);
} else {
System.out.format("[%04d]: %d reverse-responses, stale (%d clients)%n", ++count, currentOverallReverseResponses, numberOfClients);
}
break;
}
lastReverseResponsesCountDown = currentReverseResponsesCountDown;
if (observe) {
System.out.format("[%04d]: %d notifies (%d notifies/s, %d clients, %d observes)%n", ++count, currentOverallReverseResponses, roundDiv(reverseResponsesDifference, DEFAULT_TIMEOUT_SECONDS), numberOfClients, observers);
} else {
System.out.format("[%04d]: %d reverse-responses (%d reverse-responses/s, %d clients)%n", ++count, currentOverallReverseResponses, roundDiv(reverseResponsesDifference, DEFAULT_TIMEOUT_SECONDS), numberOfClients);
}
}
}
timeReverseResponseNanos = System.nanoTime() - startReverseResponseNanos;
long lastNotifiesCountDown = overallNotifiesDownCounter.get();
if (config.observe != null && lastNotifiesCountDown > 0) {
System.out.println("Observe-Requests send.");
long currentOverallSentRequests = overallRequests - overallRequestsDownCounter.get();
long lastChangeNanoRealtime = ClockUtil.nanoRealtime();
while (!overallNotifiesDone.await(DEFAULT_TIMEOUT_NANOS, TimeUnit.NANOSECONDS)) {
long currentRequestsCountDown = overallRequestsDownCounter.get();
long requestsDifference = (lastRequestsCountDown - currentRequestsCountDown);
currentOverallSentRequests += requestsDifference;
long currentNotifiesCountDown = overallNotifiesDownCounter.get();
int numberOfClients = clientCounter.get();
long notifiesDifference = (lastNotifiesCountDown - currentNotifiesCountDown);
long currentOverallNotifies = overallNotifies - currentNotifiesCountDown;
long time = 0;
if (currentNotifiesCountDown < overallNotifies) {
if (notifiesDifference == 0) {
time = ClockUtil.nanoRealtime() - lastChangeNanoRealtime;
} else {
lastChangeNanoRealtime = ClockUtil.nanoRealtime();
}
} else {
// wait extra DEFAULT_TIMEOUT_NANOS for start of reverse
// responses.
time = ClockUtil.nanoRealtime() - lastChangeNanoRealtime - DEFAULT_TIMEOUT_NANOS;
}
if (0 < TimeUnit.NANOSECONDS.toMillis(time - DEFAULT_TIMEOUT_NANOS) || (numberOfClients == 0)) {
// no new notifies for interval max, clients are stale, or
// no clients left
// adjust start time with timeout
startNotifiesNanos += time;
stale = true;
System.out.format("[%04d]: %d notifies, %d request, stale (%d clients)%n", ++count, currentOverallNotifies, currentOverallSentRequests, numberOfClients);
break;
}
lastRequestsCountDown = currentRequestsCountDown;
lastNotifiesCountDown = currentNotifiesCountDown;
System.out.format("[%04d]: %d notifies, %d request (%d notifies/s, %d clients)%n", ++count, currentOverallNotifies, currentOverallSentRequests, roundDiv(notifiesDifference, DEFAULT_TIMEOUT_SECONDS), numberOfClients);
}
}
timeNotifiesNanos = System.nanoTime() - startNotifiesNanos;
// long overallSentReverseResponses = overallReverseResponses -
// overallReverseResponsesDownCounter.getCount();
System.out.format("%d benchmark clients %s.%n", clients, stale ? "stopped" : "finished");
// stop and collect per client requests
final int[] statistic = new int[clients];
final CountDownLatch stop = new CountDownLatch(clients);
for (int index = 0; index < clients; ++index) {
final int currentIndex = index;
Runnable run = new Runnable() {
@Override
public void run() {
BenchmarkClient client = clientList.get(currentIndex);
int requests = client.destroy();
synchronized (statistic) {
statistic[currentIndex] = requests;
}
stop.countDown();
}
};
executor.execute(run);
}
stop.await();
Thread.sleep(1000);
executor.shutdown();
if (1 < clients) {
synchronized (statistic) {
Arrays.sort(statistic);
}
int grouped = 10;
int last = 0;
if (overallRequests > 500000) {
grouped = overallRequests / 50000;
}
for (int index = 1; index < clients; ++index) {
if ((statistic[index] / grouped) > (statistic[last] / grouped)) {
System.out.println(formatClientRequests(statistic, index, last));
last = index;
}
}
System.out.println(formatClientRequests(statistic, clients, last));
}
done = true;
}
Aggregations