Skip to content
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

Fix grpc-web trailer rendering for fast path #1552

Merged
merged 2 commits into from Feb 24, 2022

Conversation

jrudolph
Copy link
Member

Turns out we lost trailer rendering in the performance optimization for strict entities. This is an attempt at adding it back. Would still be good to add some tests. I currently don't have time to develop this further but maybe we can prepare the fix for the next release.

Refs #1465

@wb14123
Copy link

wb14123 commented Feb 16, 2022

Any plan to merge this in? This support is really important in my project. Otherwise my client will be broken because of the missing trailer.

Copy link
Member

@raboof raboof left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrudolph I added the necessary MiMa filter, is there anything more you were planning to look into here because you marked it as 'Draft'?

@jrudolph jrudolph marked this pull request as ready for review February 17, 2022 13:06
@jrudolph jrudolph changed the title [WIP] Fix grpc-web rendering Fix grpc-web rendering Feb 17, 2022
@jrudolph
Copy link
Member Author

I reworked the code.

I tested against akka-grpc-quickstart-scala and looked at the output which now looks reasonable when queried like this:

$ cur  'http://localhost:8080/GreeterService/SayHello' -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0' -H 'Accept: application/grpc-web-text' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate' -H 'custom-header-1: value1' -H 'Content-Type: application/grpc-web-text' -H 'X-User-Agent: grpc-web-javascript/0.1' -H 'X-Grpc-Web: 1' -H 'Origin: http://localhost:8081' -H 'Connection: keep-alive' -H 'Referer: http://localhost:8081/' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' --data-raw 'AAAAAAYKBGFvZXU=' | base64 -d |hexdump -C

00000000  00 00 00 00 0d 0a 0b 48  65 6c 6c 6f 2c 20 61 6f  |.......Hello, ao|
00000010  65 75 80 00 00 00 0f 67  72 70 63 2d 73 74 61 74  |eu.....grpc-stat|
00000020  75 73 3a 30 0d 0a                                 |us:0..|
00000026

@jrudolph
Copy link
Member Author

While with 2.1.3 the output is this, i.e. missing the trailer completely:

00000000  00 00 00 00 0d 0a 0b 48  65 6c 6c 6f 2c 20 61 6f  |.......Hello, ao|
00000010  65 75                                             |eu|
00000012

@jrudolph jrudolph changed the title Fix grpc-web rendering Fix grpc-web trailer rendering for fast path Feb 17, 2022
@inline
private final def encodeTrailer(trailer: Seq[HttpHeader]): ByteString =
ByteString(trailer.mkString("", "\r\n", "\r\n"))
private final def encodeTrailerHeaders(trailerHeaders: Iterator[(String, String)]): ByteString = {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More code is now reused between strict and streamed responses.

case DataFrame(data) =>
AbstractGrpcProtocol.encodeFrameData(codec.compress(data), codec.isCompressed, isTrailer = false)
case TrailerFrame(trailer) =>
AbstractGrpcProtocol.encodeFrameData(encodeTrailer(trailer), codec.isCompressed, isTrailer = true)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line might be another bug I introduced in the optimization: we potentially report compression but don't actually do compression.

@jrudolph jrudolph requested a review from raboof February 17, 2022 14:13
@jrudolph
Copy link
Member Author

Would be nice if you could have another look at the implementation, @raboof, given that we have no tests.

Copy link
Member

@raboof raboof left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, haven't tested it myself yet

runtime/src/main/scala/akka/grpc/GrpcProtocol.scala Outdated Show resolved Hide resolved
Co-authored-by: Arnout Engelen <arnout@engelen.eu>
@jrudolph jrudolph enabled auto-merge (squash) February 24, 2022 10:04
@jrudolph jrudolph merged commit 86cfd84 into akka:main Feb 24, 2022
@@ -87,7 +87,7 @@ object GrpcProtocol {
messageEncoding: Codec,
/** Encodes a frame as a part in a chunk stream. */
encodeFrame: Frame => ChunkStreamPart,
/** A shortcut to encode a data frame directly into a ByteString */
/** A shortcut to encode a data frame directly into a Response */
encodeDataToResponse: (ByteString, immutable.Seq[HttpHeader], Trailer) => HttpResponse,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrudolph I think Trailer could get some optimizations as well—having a cached instance for an empty Trailer, and avoiding creating a collection of 1 element and then immediately creating a new collection via map: https://github.com/akka/akka-http/blob/main/akka-http-core/src/main/scala/akka/http/scaladsl/model/Trailer.scala#L33

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For akka-grpc we are already using a cached instance here: https://github.com/jrudolph/akka-grpc/blob/efda1b1ff4a8fd9849be66a5cd8c66369f6027af/runtime/src/main/scala/akka/grpc/internal/GrpcResponseHelpers.scala#L32. For akka-http itself, you could also just omit the trailer when not needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants