Skip to content

Commit a710067

Browse files
committed
examples: Add an example for doing debug (grpc#9957)
Extensive README, a server that exposes channelz and has pauses, and a client that uses multiple channels also exposes channelz service and has a 30 second delay to allow people to run the grpcdebug tool. Fixit b/259286633
1 parent bb719bf commit a710067

File tree

8 files changed

+775
-0
lines changed

8 files changed

+775
-0
lines changed

examples/example-debug/README.md

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# gRPC Debug Example
2+
3+
The debug example uses a Hello World style server whose response includes its
4+
hostname. It demonstrates usage of the AdminInterface and the grpcdebug
5+
commandline tool.
6+
7+
The example requires grpc-java to already be built. You are strongly encouraged
8+
to check out a git release tag, since there will already be a build of grpc
9+
available. Otherwise, you must follow [COMPILING](../../COMPILING.md).
10+
11+
### Build the example
12+
13+
1. Optional: Build the hello-world-debug example client.
14+
See [the examples README](../README.md)
15+
16+
2. Build the debuggable server and client. From the
17+
`grpc-java/examples/examples-debug` directory run:
18+
19+
```bash
20+
$ ../gradlew installDist
21+
```
22+
23+
This creates the
24+
scripts `build/install/debug/bin/hostname-debuggable-server/bin/hostname-debuggable-server`
25+
that
26+
runs the example.
27+
28+
To run the debug example, run:
29+
30+
```bash
31+
$ ./build/install/debug/bin/hostname-debuggable-server/bin/hostname-debuggable-server
32+
```
33+
34+
And in a different terminal window run the client.
35+
36+
Note: You can use the standard hello-world client with no debugging enabled and
37+
still see results on the server. However, if you want to get debug information
38+
about the client you need to run the hello-world-debuggable client.
39+
40+
Simple client
41+
42+
```bash
43+
$ ../build/install/examples/bin/hello-world-client
44+
```
45+
46+
debug enabled client
47+
48+
```bash
49+
$ ./build/install/examples-debug/bin/hello-world-debuggable-client
50+
```
51+
52+
### Maven
53+
54+
If you prefer to use Maven:
55+
56+
1. Build the hello-world example client. See [the examples README](../README.md)
57+
58+
2. Run in this directory:
59+
60+
```bash
61+
$ mvn verify
62+
$ # Run the server (from the examples-debug directory)
63+
$ mvn exec:java -Dexec.mainClass=io.grpc.examples.debug.HostnameServer
64+
$ # In another terminal run the client (from the examples directory)
65+
$ cd ..
66+
$ mvn exec:java -Dexec.mainClass=io.grpc.examples.helloworld.HelloWorldClient
67+
```
68+
69+
## Using grpcdebug
70+
71+
grpcdebug is a tool that has been created to access the metrics from the
72+
channelz and health services.
73+
74+
### Installing the grpcdebug tool
75+
76+
The source code is located in a github project
77+
[grpc-ecosystem/grpcdebug](https://github.com/grpc-ecosystem/grpcdebug). You
78+
can either download [the latest built version]
79+
(https://github.com/grpc-ecosystem/grpcdebug/releases/latest) (recommended) or
80+
follow the README.md to build it yourself.
81+
82+
### Running the grpcdebug tool
83+
#### Usage
84+
`grpcdebug <target address> [flags] channelz <command> [argument]`
85+
86+
87+
| Command | Argument | Description |
88+
|:-----------|:--------------------:|:--------------------------------------------------|
89+
| channel | \<channel id or URL> | Display channel states in a human readable way. |
90+
| channels | | Lists client channels for the target application. |
91+
| server | \<server ID> | Displays server state in a human readable way. |
92+
| servers | | Lists servers in a human readable way. |
93+
| socket | \<socket ID> | Displays socket states in a human readable way. |
94+
| subchannel | \<id> | Display subchannel states in human readable way. |
95+
96+
Generally, you will start with either `servers` or `channels` and then work down
97+
to the details
98+
<br><br>
99+
100+
#### Getting overall server info
101+
```bash
102+
bin/grpcdebug/grpcdebug localhost:50051 channelz servers
103+
```
104+
This will show you the server ids with their activity
105+
```text
106+
Server ID Listen Addresses Calls(Started/Succeeded/Failed) Last Call Started
107+
2 [[::]:50051] 38/34/3 now
108+
```
109+
<br>
110+
111+
#### Getting details for a service
112+
```bash
113+
bin/grpcdebug/grpcdebug localhost:50051 channelz server 2
114+
```
115+
116+
The output will include more communication details and will show socket ids for
117+
currently connected clients
118+
119+
```text
120+
Server Id: 2
121+
Listen Addresses: [[::]:50051]
122+
Calls Started: 33
123+
Calls Succeeded: 29
124+
Calls Failed: 3
125+
Last Call Started: now
126+
---
127+
Socket ID Local->Remote Streams(Started/Succeeded/Failed) Messages(Sent/Received)
128+
19 [::1]:50051->[::1]:39834 4/3/0 3/4
129+
```
130+
131+
#### Displaying detailed info for a server side connection (socket)
132+
133+
```bash
134+
bin/grpcdebug/grpcdebug localhost:50051 channelz socket 19
135+
```
136+
137+
This will show a lot of gRPC internal information
138+
139+
```text
140+
Socket ID: 19
141+
Address: [::1]:50051->[::1]:50094
142+
Streams Started: 1
143+
Streams Succeeded: 0
144+
Streams Failed: 0
145+
Messages Sent: 0
146+
Messages Received: 1
147+
Keep Alives Sent: 0
148+
Last Local Stream Created:
149+
Last Remote Stream Created: now
150+
Last Message Sent Created:
151+
Last Message Received Created: now
152+
Local Flow Control Window: 65535
153+
Remote Flow Control Window: 1048569
154+
---
155+
Socket Options Name Value
156+
SO_LINGER [type.googleapis.com/grpc.channelz.v1.SocketOptionLinger]:{}
157+
io.grpc.netty.shaded.io.netty.channel.epoll.EpollChannelOption#TCP_CORK false
158+
WRITE_BUFFER_HIGH_WATER_MARK 65536
159+
WRITE_BUFFER_LOW_WATER_MARK 32768
160+
IP_TOS 0
161+
io.grpc.netty.shaded.io.netty.channel.epoll.EpollChannelOption#TCP_KEEPCNT 9
162+
SINGLE_EVENTEXECUTOR_PER_GROUP true
163+
SO_SNDBUF 2626560
164+
io.grpc.netty.shaded.io.netty.channel.epoll.EpollChannelOption#TCP_NOTSENT_LOWAT 0
165+
WRITE_BUFFER_WATER_MARK WriteBufferWaterMark(low: 32768, high: 65536)
166+
TCP_NODELAY true
167+
SO_RCVBUF 131072
168+
io.grpc.netty.shaded.io.netty.channel.epoll.EpollChannelOption#SO_BUSY_POLL 0
169+
IP_TRANSPARENT false
170+
SO_KEEPALIVE true
171+
io.grpc.netty.shaded.io.netty.channel.epoll.EpollChannelOption#TCP_QUICKACK false
172+
ALLOCATOR PooledByteBufAllocator(directByDefault: true)
173+
TCP_FASTOPEN_CONNECT false
174+
MESSAGE_SIZE_ESTIMATOR io.grpc.netty.shaded.io.netty.channel.DefaultMessageSizeEstimator@48d475b6
175+
WRITE_SPIN_COUNT 16
176+
SO_REUSEADDR true
177+
CONNECT_TIMEOUT_MILLIS 30000
178+
ALLOW_HALF_CLOSURE false
179+
io.grpc.netty.shaded.io.netty.channel.epoll.EpollChannelOption#EPOLL_MODE EDGE_TRIGGERED
180+
MAX_MESSAGES_PER_READ 16
181+
io.grpc.netty.shaded.io.netty.channel.epoll.EpollChannelOption#TCP_KEEPIDLE 7200
182+
AUTO_CLOSE true
183+
io.grpc.netty.shaded.io.netty.channel.epoll.EpollChannelOption#TCP_KEEPINTVL 75
184+
MAX_MESSAGES_PER_WRITE 2147483647
185+
AUTO_READ true
186+
TCP_MD5SIG null
187+
RCVBUF_ALLOCATOR io.grpc.netty.shaded.io.netty.channel.AdaptiveRecvByteBufAllocator@360691a0
188+
```
189+
#### Displaying the list of gRPC client channels
190+
Command
191+
```bash
192+
bin/grpcdebug/grpcdebug localhost:50051 channelz channels
193+
```
194+
Output
195+
```text
196+
Channel ID Target State Calls(Started/Succeeded/Failed) Created Time
197+
1 localhost:50051 READY 34/34/0
198+
3 localhost:50051 READY 16/16/0
199+
```
200+
Note: If you have a simple server that doesn't use gRPC clients to contact other
201+
servers, then this table will be empty.
202+
203+
#### Displaying details of a gRPC client channel
204+
Command
205+
```bash
206+
bin/grpcdebug/grpcdebug localhost:50051 channelz channel 3
207+
```
208+
Output
209+
```text
210+
Channel ID: 3
211+
Target: localhost:50051
212+
State: READY
213+
Calls Started: 16
214+
Calls Succeeded: 16
215+
Calls Failed: 0
216+
Created Time:
217+
---
218+
Subchannel ID Target State Calls(Started/Succeeded/Failed) CreatedTime
219+
10 [[[localhost/127.0.0.1:50051]/{}], [[localhost/0:0 READY 16/16/0
220+
```
221+
222+
#### Displaying details of a gRPC client subchannel
223+
Command
224+
```bash
225+
bin/grpcdebug/grpcdebug localhost:50051 channelz subchannel 10
226+
```
227+
Output
228+
```text
229+
Subchannel ID: 10
230+
Target: [[[localhost/127.0.0.1:50051]/{}], [[localhost/0:0:0:0:0:0:0:1:50051]/{}]]
231+
State: READY
232+
Calls Started: 16
233+
Calls Succeeded: 16
234+
Calls Failed: 0
235+
Created Time:
236+
---
237+
Socket ID Local->Remote Streams(Started/Succeeded/Failed) Messages(Sent/Received)
238+
11 127.0.0.1:48536->127.0.0.1:50051 16/16/0 12/12
239+
```

examples/example-debug/build.gradle

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
plugins {
2+
id 'application' // Provide convenience executables for trying out the examples.
3+
id 'java'
4+
5+
id "com.google.protobuf" version "0.8.17"
6+
7+
// Generate IntelliJ IDEA's .idea & .iml project files
8+
id 'idea'
9+
}
10+
11+
repositories {
12+
maven { // The google mirror is less flaky than mavenCentral()
13+
url "https://maven-central.storage-download.googleapis.com/maven2/" }
14+
mavenCentral()
15+
mavenLocal()
16+
}
17+
18+
sourceCompatibility = 1.8
19+
targetCompatibility = 1.8
20+
21+
// IMPORTANT: You probably want the non-SNAPSHOT version of gRPC. Make sure you
22+
// are looking at a tagged version of the example and not "master"!
23+
24+
// Feel free to delete the comment at the next line. It is just for safely
25+
// updating the version in our release process.
26+
def grpcVersion = '1.55.0-SNAPSHOT' // CURRENT_GRPC_VERSION
27+
def protobufVersion = '3.21.7'
28+
29+
dependencies {
30+
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
31+
implementation "io.grpc:grpc-stub:${grpcVersion}"
32+
implementation "io.grpc:grpc-services:${grpcVersion}"
33+
compileOnly "org.apache.tomcat:annotations-api:6.0.53"
34+
runtimeOnly "io.grpc:grpc-netty-shaded:${grpcVersion}"
35+
36+
testImplementation 'junit:junit:4.13.2'
37+
testImplementation "io.grpc:grpc-testing:${grpcVersion}"
38+
}
39+
40+
protobuf {
41+
protoc {
42+
artifact = "com.google.protobuf:protoc:${protobufVersion}"
43+
}
44+
plugins {
45+
grpc {
46+
artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
47+
}
48+
}
49+
generateProtoTasks {
50+
all()*.plugins {
51+
grpc {}
52+
}
53+
}
54+
}
55+
56+
startScripts.enabled = false
57+
58+
task HelloWorldDebuggableClient(type: CreateStartScripts) {
59+
mainClass = 'io.grpc.examples.debug.HelloWorldDebuggableClient'
60+
applicationName = 'hello-world-debuggable-client'
61+
outputDir = new File(project.buildDir, 'tmp/scripts/' + name)
62+
classpath = startScripts.classpath
63+
}
64+
65+
task HostnameDebuggableServer(type: CreateStartScripts) {
66+
mainClass = 'io.grpc.examples.debug.HostnameDebuggableServer'
67+
applicationName = 'hostname-debuggable-server'
68+
outputDir = new File(project.buildDir, 'tmp/scripts/' + name)
69+
classpath = startScripts.classpath
70+
}
71+
72+
applicationDistribution.into('bin') {
73+
from(HelloWorldDebuggableClient)
74+
from(HostnameDebuggableServer)
75+
fileMode = 0755
76+
}

0 commit comments

Comments
 (0)