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

Quick Start request example doesn't work for me #97

Closed
breun opened this issue Jan 20, 2025 · 12 comments
Closed

Quick Start request example doesn't work for me #97

breun opened this issue Jan 20, 2025 · 12 comments
Assignees

Comments

@breun
Copy link

breun commented Jan 20, 2025

I know Spring gRPC is still experimental at this point, but I was interested in trying it out, so I created a new Spring Boot 3.4.1 project with Web and gRPC dependencies on https://start.spring.io. I followed the instructions on https://docs.spring.io/spring-grpc/reference/getting-started.html to add the hello.proto file, generate the sources, and then added the GrpcServerService. I built and ran the service, and then executed tried to see it in action, but I got this:

❯ grpcurl -d '{"name":"Hi"}' -plaintext localhost:9090 Simple.SayHello
Failed to dial target host "localhost:9090": connection error: desc = "transport: error while dialing: dial tcp 127.0.0.1:9090: connect: connection refused"

So, apparently something is wrong with either my service, or my request to the service. Should this documentation be up-to-date?

The startup messages of the application don't show anything starting on port 9090. I also tried the Tomcat port (8080), but got no result there either.

Is there anything else I need to get the server started, or should I query the service in a different way?

@onobc
Copy link
Collaborator

onobc commented Jan 20, 2025

Hi @breun ,
Sorry you are having trouble w/ the getting started instructions. The documentation should be up-to-date but if it is not we will make sure that it is. I will repeat the steps you have done and see what I see and will report back here w/ that info.

Thanks

@onobc onobc self-assigned this Jan 20, 2025
@onobc
Copy link
Collaborator

onobc commented Jan 20, 2025

I was able to reproduce exaclty what you are seeing. You are correct, the docs are out of date. We try our best to keep them live and in sync but... (me raising hand).

Summary

So here is whats going on...

The quick start docs suggests adding the "spring-web" dependency.
When Spring gRPC sees the "spring-web" dep. it assumes that you want to run with the Servlet Server.
When running w/ the "servlet server" all other server factories (e.g. Netty) are disabled.
However, the "servlet server" also requires the io.grpc:grpc-servlet-jakarta dependency (missing from docs) and the server.http2.enabled=true application property (missing from the docs).

Without the above requirements, the end result is the server starts with no server factory and therefore no services.

Note

We need to improve this on the framework

Workarounds

Let's talk workarounds...

If you want to use the "Servlet Server" please add the io.grpc:grpc-servlet-jakarta dependency and add the following application props:

server.port=9090
server.http2.enabled=true

Note

The server.port=9090 is just for convenience to avoid changing your gRPC calls (and grpcurl) to Tomcat port (e.g. 8080)

If you don't want to use the "Servlet Server" please remove the org.springframework.boot:spring-boot-starter-web dependency.

After either of the above actions the grpcurl command works.

Next

In the meantime, we will get the docs updated and also work on making the "web" configuration a bit easier to consume.

Thank you for the detailed report. Please let us know if you have any issues w/ the workarounds above.

onobc added a commit to onobc/spring-grpc that referenced this issue Jan 20, 2025
Updates the fix-getting-started.adoc section of the reference
guide to remove the requirement of the "web" and "graalvm"
dependencies as the former requires other information besides
dependencies to work properly and the latter is just complication
that is not needed for a simple quick start.

See spring-projects-experimental#97
onobc added a commit to onobc/spring-grpc that referenced this issue Jan 20, 2025
Updates the fix-getting-started.adoc section of the reference
guide to remove the requirement of the "web" and "graalvm"
dependencies as the former requires other information besides
dependencies to work properly and the latter is just complication
that is not needed for a simple quick start.

See spring-projects-experimental#97
onobc added a commit to onobc/spring-grpc that referenced this issue Jan 20, 2025
Updates the fix-getting-started.adoc section of the reference
guide to remove the requirement of the "web" and "graalvm"
dependencies as the former requires other information besides
dependencies to work properly and the latter is just complication
that is not needed for a simple quick start.

See spring-projects-experimental#97
@onobc
Copy link
Collaborator

onobc commented Jan 20, 2025

While there are other improvements to be made, the specific instance of the docs being out of sync are fixed with #98.

@onobc onobc closed this as completed Jan 20, 2025
dsyer pushed a commit that referenced this issue Jan 21, 2025
Updates the fix-getting-started.adoc section of the reference
guide to remove the requirement of the "web" and "graalvm"
dependencies as the former requires other information besides
dependencies to work properly and the latter is just complication
that is not needed for a simple quick start.

See #97
@breun
Copy link
Author

breun commented Jan 21, 2025

Thanks, adding io.grpc:grpc-servlet-jakarta and the server.* properties made it work. 👍

Another remark: maybe this is already on your radar, but it would be nice to document why a user might want to use the servlet server or not. The same goes for using shaded Netty or not. Let me know if you'd like me to create separate issues for these things. (But I don't have the answers.)

@breun
Copy link
Author

breun commented Jan 21, 2025

I also get an error when trying the quick start streaming RPC call (which maybe should also be part of the quick start example?):

❯ grpcurl -d '{"name":"Hi"}' -plaintext localhost:9090 Simple.StreamHello
{
  "message": "Hello(0) ==\u003e Hi"
}
{
  "message": "Hello(1) ==\u003e Hi"
}
{
  "message": "Hello(2) ==\u003e Hi"
}
{
  "message": "Hello(3) ==\u003e Hi"
}
{
  "message": "Hello(4) ==\u003e Hi"
}
{
  "message": "Hello(5) ==\u003e Hi"
}
{
  "message": "Hello(6) ==\u003e Hi"
}
ERROR:
  Code: Unavailable
  Message: closing transport due to: connection error: desc = "error reading from server: EOF", received prior goaway: code: ENHANCE_YOUR_CALM, debug data: "Connection [3], Too much overhead so the connection will be closed"

Is this expected?

@dsyer
Copy link
Collaborator

dsyer commented Jan 21, 2025

Apparently it's a Tomcat issue/feature (https://stackoverflow.com/questions/61413934/http2-err-connection-closed-too-much-overhead). I'll see if I can shed any more light and find a configuration to fix it.

UPDATE: it's actually grpcurl that's more of a problem. the service is working, and if you write an integration test it will pass, e.g.

@Test
@DirtiesContext
void streamResponds() {
	Iterator<HelloReply> response = stub.streamHello(HelloRequest.newBuilder().setName("Alien").build());
	assertEquals("Hello(0) ==> Alien", response.next().getMessage());
	while (response.hasNext()) {
		log.info(response.next().getMessage());
	}
}

It seems like grpcurl sends a lot of PING frames, which is actually the thing that Tomcat hates. The native grpc-java client doesn't do that, so it works fine.

@dsyer
Copy link
Collaborator

dsyer commented Jan 21, 2025

You can configure Tomcat to ignore those (turns out it's not the pings, it's the WINDOW_UPDATE frames that grpcurl sends):

@Bean
public TomcatConnectorCustomizer customizer() {
	return (connector) -> {
		for (UpgradeProtocol protocol : connector.findUpgradeProtocols()) {
			if (protocol instanceof Http2Protocol http2Protocol) {
				http2Protocol.setOverheadWindowUpdateThreshold(0);
			}
		}
	};
}

@panic08
Copy link
Contributor

panic08 commented Feb 1, 2025

Speaking of which, if you don't remove the org.springframework.boot:spring-boot-starter-web dependency and still do everything as @onobc said, it will indeed work in that case, but it still won't work in tests with @SpringBootTest.

@dsyer
Copy link
Collaborator

dsyer commented Feb 1, 2025

The tomcat sample works with @SpringBootTest AFAIK. What’s different about that?

@panic08
Copy link
Contributor

panic08 commented Feb 11, 2025

I'm currently trying to help create the grpc-server-sample-with-spring-boot-starter-web module related to issue #99 and I've encountered this problem again.

You can for samples/grpc-server add spring-boot-starter-web and grpc-servlet-jakarta dependency and in application.properties add server.port=9090 and server.http2.enabled=true , then run the test and see:
Caused by: org.springframework.util.PlaceholderResolutionException: Could not resolve placeholder 'local.grpc.port' in value “${local.grpc.port}”

This is most likely due to the fact that this solution does not work in tests, as I said. In my third party test project I have similar test code, however without @LocalGrpcPort, and in stacktrace I see:
Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: getsockopt: /0.0.0.0.0:9090.
I don't know what this is related to.

Basically, in the same project as I just checked, the same problem I described above is reproduced with @LocalGrpcPort.

@panic08
Copy link
Contributor

panic08 commented Feb 11, 2025

Funny thing is, I fixed this problem now by adding webEnvironment to @SpringBootTest. It goes like this:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)

However, the problem with @LocalGrpcPort remained.

@dsyer
Copy link
Collaborator

dsyer commented Feb 11, 2025

If you're running in a servlet container the local port is the normal Spring MVC one (local.server.port). Check out the tomcat sample to see it working, as already mentioned. Chris (@onobc) is also working on new starters in #106, so I would wait and see what he does before you do anything else that might end up in PR.

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

No branches or pull requests

4 participants