SourceForge.net Logo

Home | SF Project | Download | Forum | Bugs | History | For Coders | HowTo | Commentary | TODO | Support This Project


Basic | Connection | Advanced | Secure | Certificate | JMX | XML

Connection Behavior HowTo

You should find the script proxy.sh in the scripts directory, and it will look something like this:
	#!/bin/sh
	
	. env.sh
	
	PROXY_PROPS="-Dlisten.port=9090 -Dtarget.host=dev1 -Dtarget.port=9090"
	#PROXY_PROPS="$PROXY_PROPS -Dlatency.millis=250"
	#PROXY_PROPS="$PROXY_PROPS -Dpacket.loss.rate=100"
	#PROXY_PROPS="$PROXY_PROPS -Dbandwidth.throttle=50"
	#PROXY_PROPS="$PROXY_PROPS -Denable.connection.loss=true"
	
	java $PROXY_PROPS -Xmx1024m -cp "$CP" com.moneybender.proxy.Proxy
The lines that change connection behavior are commented, and can be used individually or in concert by the ones with the desired affect.

JMX view of Decorators

You can now use your favorite JMX tool to view Decorator state. Here's what you see in JConsole:

Injecting Latency

Uncomment the latency line:
	PROXY_PROPS="$PROXY_PROPS -Dlatency.millis=250"
and change the latency to suit. The latency is stated in milliseconds, and each packet that is received by the proxy will be delayed by this amount before being sent to the target receiver. This can be used to simulate connections that have a high latency, such as through a satellite. If you're developing a web service, web application, or other network service, you can get a rough gauge of your users' experience when using the service.

A connection through a satellite in geostationary orbit (22,236 miles above sea level) will experience roughly 240 milliseconds of delay for the total round-trip due to the propagation delay, so

-Dlatency.millis=240
should simulate the affect pretty closely.

Injecting Bandwidth limits

Uncomment the bandwidth line:
	PROXY_PROPS="$PROXY_PROPS -Dbandwidth.throttle=50"
This will limit the bandwidth to 50 KBPS. This is useful to simulate the affect of a slow connection such as a dial-up modem. Use this to see what a web site or web application's behavior might be on a slow connection.

Injecting Packet Loss

Uncomment the packet-loss line:
	PROXY_PROPS="$PROXY_PROPS -Dpacket.loss.rate=100"
This specifies the denominator - so a packet-loss rate of 100 will drop one of every 100 packets. A packet-loss rate of 30 would lose 1 of every 30 packets. I expect that this might change in the future to be more flexible.

Making the connection unreliable

Uncomment the connection-loss line:
	PROXY_PROPS="$PROXY_PROPS -Denable.connection.loss=true"
This enables the connection loss, but you have to trigger it. Typically, this will occur in one of two ways.

In the first approach, you need to have a Java program that starts and stops the Proxy. Look at the main() method in Proxy.java and ProxyTest.java for examples. After your program starts the proxy, it can do some stuff that generates traffic. At the point in your code where you want to simulate a network failure, call ConnectionLossDecorator.networkOff(). When you want to simulate the return of the network, call ConnectionLossDecorator.networkOff(). Your code might look something like this:

	Proxy proxy = new Proxy();
	proxy.start(new ProxySettings());
	
	System.out.println("Sleep");
	Thread.sleep(30000);
	
	System.out.println("Break connections");
	ConnectionLossDecorator.networkOff();
	
	Thread.sleep(5000);
	System.out.println("Fix connections");
	ConnectionLossDecorator.networkOn();
	
	System.out.println("wait");
	synchronized(proxy) {
		proxy.wait();
	}
This can be useful in integration tests when you want to simulate network loss, and see how your application behaves.

Here's how networkOff() works. When you call it, it sets a flag. All channels will fail on the next read() when that flag is set, and the channels will therefore close with an I/O error. When the networkOn() is called, the flag is cleared and new channels will work normally.

In the second approach, you don't need a Java program, but instead you manually or programmatically toggle the network state via JMX. You can use JMX to do this. Look at DecoratorState...Operations in JConsole:

Use the buttons to enable or disable network connectivity. When the proxy starts, the network will be enabled by default. For example, start the proxy:

	./proxy.sh
	2008-04-06 08:02:07,687 INFO  [ByteReaderFactory] - Connection loss enabled.  Call ConnectionLossDecorator.networkOn() and ConnectionLossDecorator.networkOff() to toggle.
	2008-04-06 08:02:07,734 INFO  [SocketSelectHandler] - Listening on port 9090, target at dev1:9090
Connect to the proxy with JConsole, and browse to the DecoratorControl Operations. Then start your application. I'll use curl as an example:
	curl -D - --proxy localhost:9090 -O http://suse.mirrors.tds.net/pub/opensuse/distribution/10.3/iso/dvd/openSUSE-10.3-GM-DVD-i386.iso
Next, click the networkOff operation. You should see curl fail:
	curl -D - --proxy localhost:9090 -O http://suse.mirrors.tds.net/pub/opensuse/distribution/10.3/iso/dvd/openSUSE-10.3-GM-DVD-i386.iso
	  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
	                                 Dload  Upload   Total   Spent    Left  Speed
	  0     0    0     0    0     0      0      0 --:--:--  0:00:15 --:--:--     0HTTP/1.1 200 OK
	Date: Sun, 06 Apr 2008 13:01:00 GMT
	Server: Apache/2.2.0
	Last-Modified: Thu, 27 Sep 2007 15:50:25 GMT
	ETag: "1073001d-69bd800-edb61240"
	Accept-Ranges: bytes
	Content-Length: 4405843968
	Expires: Mon, 07 Apr 2008 13:04:04 GMT
	Content-Type: application/octet-stream
	Via: 1.1 dev1:9090
	
	  0 4201M    0 1338k    0     0  69867      0 17:31:00  0:00:19 17:30:41  296k
	curl: (18) transfer closed with 4404473088 bytes remaining to read
That's all there is to it.