At work we use Netflix's Feign Client to help with requests between services. However, I'm confused about its apparent lack of ability to stream data, especially given Netflix's well known business model of streaming video. I clearly am missing something here.
To explain, say Service A
asks the Feign Client of Service B
for a stream of data and Service B
sends the stream in the response. At this point, the execute()
method in the Feign Client gets called:
@Override public Response execute(Request request, Options options) throws IOException {
HttpURLConnection connection = convertAndSend(request, options);
return convertResponse(connection);
}
HttpURLConnection convertAndSend(Request request, Options options) throws IOException {
final HttpURLConnection connection = (HttpURLConnection) new URL(request.url()).openConnection();
/** SNIP **/
if (request.body() != null) {
if (contentLength != null) {
connection.setFixedLengthStreamingMode(contentLength);
} else {
connection.setChunkedStreamingMode(8196);
}
connection.setDoOutput(true);
OutputStream out = connection.getOutputStream();
if (gzipEncodedRequest) {
out = new GZIPOutputStream(out);
}
try {
out.write(request.body()); // PROBLEM
} finally {
try {
out.close();
} catch (IOException suppressed) {
}
}
}
return connection;
}
The line labelled PROBLEM
is what confuses me.
- The
request
object doesn't even have any sort of stream to read, just abyte[] body
. - On the outgoing end, the entire body is written into the
OutputStream
at once. Shouldn't it chunk the data instead?
For example
// pseudocode
try {
location = 0
bufferSize = 2048
buffer = request.body().read(location, bufferSize)
while(out.readyToRead() && buffer.length > 0) {
out.write(buffer)
location += bufferSize
buffer = request.body().read(location, bufferSize)
}
}
If the request had a stream instead of just byte[] body
, you could improve that even further to send data as it becomes available.
I'm very new to this area of service architecture. What am I missing?
Feign was designed for control plane apis, which often don't benefit by streaming upwards. Streaming downwards is supported, though.
I've no concern with being more efficient with regards to how buffering works (ex. alternative to byte array). Just bear in mind that most of feign's design revolves around templating forms (json or xml) and reusing these as much as possible (ex. on retransmit, buffered + fixed length is easy and predictable).
I think I'd be most happy about a "streaming" design if it were coupled to the http client. IOTW, a subtype that addresses streaming in a way that makes sense in the transport. For example, InputStream for regular java, OkIo buffer for OkHttp, Netty Buffer for Netty, etc.
Spencer opened this for the investigation https://github.com/Netflix/feign/issues/220