问题
We are currently using Apache Httpclient in our custom load test framework. I have to implement support for WebSocket testing, and since HttpClient does not support WebSockets, I am looking for alternatives. So, I've been playing with OkHttp and Async Http Client. In general, I could use both as a replacement, but either one gives me a few challenges I need to tackle. Here's the ones I'm facing with OkHttp:
- OkHttp uses global static state in
com.squareup.okhttp.internal.Internal
which seems a little bit scary to me. In our framework, we launch lots of threads which in turn execute what we call request flows. Each thread would get its own HttpClient instance. It seems, with OkHttp you cannot have multiple independent OkHttpClient instances in one VM because they would interfere due to this static stuff. I seem to be able to work around this problem by using one OkHttpClient instance with a CookieHandler that delegates to thread-scoped CookieHandlers. I might have to do the same with ConnectionPools. Am I on the right track here? - I need to be able to set the local address. We have client machines with multiple NICs which have to be evenly used. That's no problem with Apache HttpClient and AsyncHttpClient. How can this be done with OkHttp?
Update/Solution:
Digging through the code again after Jesse posted his comments, I realized that the Internal
singleton does not keep state. I guess I was irritated just by the fact that I found a singleton in the codebase even though is does not do any harm.
I was able to set the local address using a custom Socket Factory as Jesse suggested:
public class LocalAddressSocketFactory extends SocketFactory {
private static final String ERROR_MSG = "On unconnected sockets are supported";
private final SocketFactory delegate;
private final Provider<InetAddress> localAddressProvider;
public LocalAddressSocketFactory(final SocketFactory delegate,
final Provider<InetAddress> localAddressProvider) {
this.delegate = delegate;
this.localAddressProvider = localAddressProvider;
}
@Override
public Socket createSocket() throws IOException {
Socket socket = delegate.createSocket();
socket.bind(new InetSocketAddress(localAddressProvider.get(), 0));
return socket;
}
@Override
public Socket createSocket(final String remoteAddress, final int remotePort)
throws IOException, UnknownHostException {
throw new UnsupportedOperationException(ERROR_MSG);
}
@Override
public Socket createSocket(final InetAddress remoteAddress, final int remotePort)
throws IOException {
throw new UnsupportedOperationException(ERROR_MSG);
}
@Override
public Socket createSocket(final String remoteAddress, final int remotePort,
final InetAddress localAddress, final int localPort)
throws IOException, UnknownHostException {
throw new UnsupportedOperationException(ERROR_MSG);
}
@Override
public Socket createSocket(final InetAddress remoteAddress, final int remotePort,
final InetAddress localAddress, final int localPort)
throws IOException {
throw new UnsupportedOperationException(ERROR_MSG);
}
}
This class relies on the fact the OkHttp only creates unconnected Sockets. I'd appreciate it if this could be documented. OkHttpClient allows a custom SocketFactory to be set, but you have to find out yourself how it is used. I just submitted a pull request enhancing the Javadocs: https://github.com/square/okhttp/pull/1626.
来源:https://stackoverflow.com/questions/30118534/global-state-and-local-address-in-okhttp