Skip to content

Commit f2f1209

Browse files
buchgrnmittler
authored andcommitted
Fix race for stream id in OkHttpClientTransport.
When running benchmarks using the okhttp transport with lots of streams per channel we would see the occasional GOAWAY frame with the server logging exceptions of the like "io.netty.handler.codec.http2.Http2Exception: Request stream 575 is behind the next expected stream 583". As quickly identified by @ejona86, there is a race between creating a new stream id and writing the header on the wire. Putting both under the same lock ensures that those two always go together. After this change the errors disappeared. The perf impact should be small as the actual write to the socket doesn't happen within the lock, but only the scheduling of the write.
1 parent b10aaf8 commit f2f1209

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

okhttp/src/main/java/io/grpc/transport/okhttp/OkHttpClientTransport.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -168,23 +168,29 @@ public class OkHttpClientTransport implements ClientTransport {
168168
}
169169

170170
@Override
171-
public OkHttpClientStream newStream(MethodDescriptor<?, ?> method, Metadata.Headers headers,
172-
ClientStreamListener listener) {
171+
public OkHttpClientStream newStream(MethodDescriptor<?, ?> method,
172+
Metadata.Headers headers,
173+
ClientStreamListener listener) {
173174
Preconditions.checkNotNull(method, "method");
174175
Preconditions.checkNotNull(headers, "headers");
175176
Preconditions.checkNotNull(listener, "listener");
176-
OkHttpClientStream clientStream = OkHttpClientStream.newStream(listener,
177-
frameWriter, this, outboundFlow);
177+
178+
OkHttpClientStream clientStream =
179+
OkHttpClientStream.newStream(listener, frameWriter, this, outboundFlow);
180+
181+
String defaultPath = "/" + method.getName();
182+
List<Header> requestHeaders =
183+
Headers.createRequestHeaders(headers, defaultPath, defaultAuthority);
184+
178185
synchronized (lock) {
179186
if (goAway) {
180187
throw new IllegalStateException("Transport not running", goAwayStatus.asRuntimeException());
181-
} else {
182-
assignStreamId(clientStream);
183188
}
189+
190+
assignStreamId(clientStream);
191+
frameWriter.synStream(false, false, clientStream.id(), 0, requestHeaders);
184192
}
185-
String defaultPath = "/" + method.getName();
186-
frameWriter.synStream(false, false, clientStream.id(), 0,
187-
Headers.createRequestHeaders(headers, defaultPath, defaultAuthority));
193+
188194
return clientStream;
189195
}
190196

0 commit comments

Comments
 (0)