-
Notifications
You must be signed in to change notification settings - Fork 882
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Netty async stability fixes #173
Conversation
- Prevent possible use-after-free bug for Streaming responses - Account for half closed connection (closed by remote) and signal back to SdkResponseHandler asn an IOException Fixes aws#146
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
@@ -60,6 +60,14 @@ | |||
|
|||
<!--Reactive Dependencies--> | |||
<dependency> | |||
<groupId>io.netty</groupId> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can probably remove this. Was testing the perf of native SSL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
@@ -143,7 +145,7 @@ private static int port(URI uri) { | |||
|
|||
private SslContext sslContext(String scheme) { | |||
if (scheme.equalsIgnoreCase("https")) { | |||
SslContextBuilder builder = SslContextBuilder.forClient().sslProvider(defaultClientProvider()); | |||
SslContextBuilder builder = SslContextBuilder.forClient().sslProvider(SslProvider.JDK); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This you can revert for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverted
ctx.channel().close() | ||
.addListener(channelFuture -> requestContext.channelPool().release(ctx.channel())); | ||
private static void removePerRequestHandlers(ChannelHandlerContext ctx) { | ||
removePerRequestHandlers(ctx, HttpStreamsClientHandler.class, ReadTimeoutHandler.class, WriteTimeoutHandler.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can get rid of this and remove them before the request starts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 looks like we were already doing that; removed
ByteBuf fullContent = ((FullHttpResponse) msg).content(); | ||
final ByteBuffer bb = copyToByteBuffer(fullContent); | ||
fullContent.release(); | ||
requestContext.handler().onStream(new FullResponseContentPublisher(channelContext, bb)); | ||
} | ||
|
||
if (msg instanceof LastHttpContent) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you remove the removePerRequsetHandlers method I think you can combine this with the FullHttpResponse branch.
} | ||
} | ||
|
||
@Override | ||
public void abort() { | ||
if (channel != null) { | ||
channel.disconnect().addListener(ignored -> context.channelPool().release(channel)); | ||
channel.close().addListener(ignored -> context.channelPool().release(channel)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a closeAndRelease method would be good here too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored into closeAndRelease
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any helpful comments we could add to the SPI based on the changes you had to make here?
bundle/pom.xml
Outdated
@@ -54,6 +54,10 @@ | |||
<configuration> | |||
<artifactSet> | |||
<includes> | |||
<include>joda-time:joda-time</include> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where are we still using joda?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Removed
} | ||
} catch (Exception e) { | ||
subscriber.onError(e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment or logging here?
} | ||
} | ||
|
||
private void close() { | ||
// Completion handled by response handler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No longer true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this got left it while I was resolving some merge conflicts
.statusCode(response.status().code()) | ||
.statusText(response.status().reasonPhrase()) | ||
.build(); | ||
.headers(fromNettyHeaders(response.headers())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh man, are we fixed or aligned?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, realigned this.
a559dc1
to
10927ca
Compare
ByteBuf fullContent = ((FullHttpResponse) msg).content(); | ||
final ByteBuffer bb = copyToByteBuffer(fullContent); | ||
fullContent.release(); | ||
requestContext.handler().onStream(new FullResponseContentPublisher(channelContext, bb)); | ||
Subscriber<? super ByteBuffer> subscriber = channelContext.channel().attr(ChannelAttributeKeys.SUBSCRIBER_KEY).get(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need to stick the subscriber in an attribute if we complete on the same message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah since the FullResponseContentPublisher
is the one that sets the subscriber in the ChannelContext
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { | ||
RequestContext requestContext = ctx.channel().attr(REQUEST_CONTEXT_KEY).get(); | ||
log.error("Exception processing request: {}", requestContext.sdkRequest(), cause); | ||
runAndLogError("SdkHttpResponseHandler threw an exception", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we mark complete here too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
requestContext.handler().complete(); | ||
} finally { | ||
finalizeRequest(requestContext, channelContext); | ||
// Run in the event loop to avoid sync issues in finalizeRequest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should be guaranteed to be running on the channel thread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double checked this and looks like HttpStreamsClientHandler
does guarantee this. Thanks for pointing it out!
10927ca
to
6992171
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Nice work!
|
||
// TODO make these configurable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you modify this TODO to only add the write here, remove it when we finished writing, add the read then, then remove read when the request if finished?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 done.
6992171
to
bc7060d
Compare
SdkResponseHandler
in situations where remote end of the TCP connection is unexpectedly closed by the serviceBuilds on @shorea's work here: https://github.com/aws/aws-sdk-java-v2/tree/shorea-dongie-perf-share
Fixes #146