0
# Admin Services
1
2
Collection of standard administrative services for gRPC servers including all built-in observability and management services. Provides a convenient way to add multiple admin services to your gRPC server.
3
4
## Capabilities
5
6
### AdminInterface
7
8
Utility class that provides a collection of standard gRPC administrative services, including channelz, health checking, and server reflection.
9
10
```java { .api }
11
/**
12
* Provides a class of services for exposing the overall state of gRPC activity.
13
* Offers standard administrative services in a single collection.
14
*/
15
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/7929")
16
@ThreadSafe
17
public final class AdminInterface {
18
19
/**
20
* Returns a list of gRPC's built-in admin services
21
* @return List of ServerServiceDefinition containing standard admin services
22
*/
23
public static List<ServerServiceDefinition> getStandardServices();
24
}
25
```
26
27
**Usage Examples:**
28
29
```java
30
import io.grpc.Server;
31
import io.grpc.ServerBuilder;
32
import io.grpc.services.AdminInterface;
33
34
// Add all standard admin services to your server
35
public class AdminEnabledServer {
36
37
public static void main(String[] args) throws Exception {
38
Server server = ServerBuilder.forPort(8080)
39
// Add all standard admin services at once
40
.addServices(AdminInterface.getStandardServices())
41
42
// Add your business services
43
.addService(new UserService())
44
.addService(new OrderService())
45
.build();
46
47
server.start();
48
System.out.println("Server started with admin services on port 8080");
49
50
// Print available admin services
51
System.out.println("Available admin services:");
52
AdminInterface.getStandardServices().forEach(service ->
53
System.out.println(" - " + service.getServiceDescriptor().getName())
54
);
55
56
server.awaitTermination();
57
}
58
}
59
```
60
61
## Standard Services Included
62
63
The AdminInterface provides the following standard services:
64
65
### Channelz Service
66
- **Service Name**: `grpc.channelz.v1.Channelz`
67
- **Purpose**: Runtime introspection and debugging
68
- **Endpoints**: Channel, server, and socket information
69
70
### Health Service
71
- **Service Name**: `grpc.health.v1.Health`
72
- **Purpose**: Health checking for load balancers
73
- **Endpoints**: Health status reporting
74
75
### Server Reflection Service
76
- **Service Name**: `grpc.reflection.v1.ServerReflection`
77
- **Purpose**: Service discovery and debugging tools
78
- **Endpoints**: Protocol buffer reflection
79
80
## Production Server Example
81
82
```java
83
import io.grpc.Server;
84
import io.grpc.ServerBuilder;
85
import io.grpc.services.AdminInterface;
86
import io.grpc.protobuf.services.HealthStatusManager;
87
88
public class ProductionServer {
89
private final Server server;
90
private final HealthStatusManager healthManager;
91
92
public ProductionServer(int port) {
93
// Create health manager for additional control
94
this.healthManager = new HealthStatusManager();
95
96
this.server = ServerBuilder.forPort(port)
97
// Add standard admin services
98
.addServices(AdminInterface.getStandardServices())
99
100
// Override health service with our managed instance
101
.addService(healthManager.getHealthService())
102
103
// Add business services
104
.addService(new UserService())
105
.addService(new OrderService())
106
.addService(new PaymentService())
107
.build();
108
}
109
110
public void start() throws IOException {
111
server.start();
112
113
// Set initial health status
114
healthManager.setStatus("", ServingStatus.SERVING);
115
healthManager.setStatus("com.example.UserService", ServingStatus.SERVING);
116
healthManager.setStatus("com.example.OrderService", ServingStatus.SERVING);
117
healthManager.setStatus("com.example.PaymentService", ServingStatus.SERVING);
118
119
System.out.println("Production server started on port " + server.getPort());
120
System.out.println("Admin services available for monitoring and debugging");
121
122
// Add shutdown hook
123
Runtime.getRuntime().addShutdownHook(new Thread(this::gracefulShutdown));
124
}
125
126
private void gracefulShutdown() {
127
System.out.println("Initiating graceful shutdown...");
128
129
// Mark services as not serving
130
healthManager.setStatus("", ServingStatus.NOT_SERVING);
131
132
// Wait for load balancers to drain traffic
133
try {
134
Thread.sleep(10000); // 10 second drain period
135
} catch (InterruptedException e) {
136
Thread.currentThread().interrupt();
137
}
138
139
// Enter terminal state and shutdown
140
healthManager.enterTerminalState();
141
server.shutdown();
142
143
try {
144
if (!server.awaitTermination(30, TimeUnit.SECONDS)) {
145
server.shutdownNow();
146
}
147
} catch (InterruptedException e) {
148
server.shutdownNow();
149
Thread.currentThread().interrupt();
150
}
151
}
152
153
public void awaitTermination() throws InterruptedException {
154
server.awaitTermination();
155
}
156
}
157
```
158
159
## Development Server with Enhanced Admin Services
160
161
```java
162
import io.grpc.Server;
163
import io.grpc.ServerBuilder;
164
import io.grpc.services.AdminInterface;
165
import io.grpc.protobuf.services.ProtoReflectionServiceV1;
166
import io.grpc.protobuf.services.BinaryLogs;
167
168
public class DevelopmentServer {
169
170
public static void main(String[] args) throws Exception {
171
// Enhanced development server with additional debugging capabilities
172
BinaryLog binaryLog = BinaryLogs.createBinaryLog(); // Debug logging
173
174
Server server = ServerBuilder.forPort(8080)
175
// Add standard admin services
176
.addServices(AdminInterface.getStandardServices())
177
178
// Add enhanced reflection service (latest version)
179
.addService(ProtoReflectionServiceV1.newInstance())
180
181
// Enable binary logging for debugging
182
.setBinaryLog(binaryLog)
183
184
// Add business services
185
.addService(new UserService())
186
.addService(new OrderService())
187
.build();
188
189
server.start();
190
191
System.out.println("Development server started on port 8080");
192
System.out.println("\nAvailable debugging tools:");
193
System.out.println(" grpcurl -plaintext localhost:8080 list");
194
System.out.println(" grpcurl -plaintext localhost:8080 grpc.health.v1.Health/Check");
195
System.out.println(" grpcurl -plaintext localhost:8080 grpc.channelz.v1.Channelz/GetTopChannels");
196
197
server.awaitTermination();
198
}
199
}
200
```
201
202
## Microservices Architecture Integration
203
204
```java
205
public class MicroserviceWithAdminServices {
206
private final Server server;
207
private final HealthStatusManager healthManager;
208
private final MetricRecorder metricRecorder;
209
210
public MicroserviceWithAdminServices(String serviceName, int port) {
211
this.healthManager = new HealthStatusManager();
212
this.metricRecorder = MetricRecorder.newInstance();
213
214
this.server = ServerBuilder.forPort(port)
215
// Standard admin services for observability
216
.addServices(AdminInterface.getStandardServices())
217
218
// Override with managed health service
219
.addService(healthManager.getHealthService())
220
221
// Add service-specific business logic
222
.addService(createBusinessService(serviceName))
223
224
// Add interceptors for metrics
225
.intercept(new MetricsInterceptor(metricRecorder))
226
.build();
227
}
228
229
private BindableService createBusinessService(String serviceName) {
230
switch (serviceName) {
231
case "user-service":
232
return new UserService();
233
case "order-service":
234
return new OrderService();
235
case "payment-service":
236
return new PaymentService();
237
default:
238
throw new IllegalArgumentException("Unknown service: " + serviceName);
239
}
240
}
241
242
public void start() throws IOException {
243
server.start();
244
245
// Set healthy status
246
healthManager.setStatus("", ServingStatus.SERVING);
247
248
// Start metrics reporting
249
startMetricsReporting();
250
251
System.out.println("Microservice started on port " + server.getPort());
252
System.out.println("Admin services enabled for service mesh integration");
253
}
254
255
private void startMetricsReporting() {
256
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
257
258
scheduler.scheduleAtFixedRate(() -> {
259
metricRecorder.setCpuUtilizationMetric(getCurrentCpuUsage());
260
metricRecorder.setMemoryUtilizationMetric(getCurrentMemoryUsage());
261
metricRecorder.setQpsMetric(getCurrentQps());
262
}, 0, 30, TimeUnit.SECONDS);
263
}
264
265
private double getCurrentCpuUsage() {
266
// Implementation to get CPU usage
267
return Math.random() * 0.8; // Example
268
}
269
270
private double getCurrentMemoryUsage() {
271
Runtime runtime = Runtime.getRuntime();
272
return (double) (runtime.totalMemory() - runtime.freeMemory()) / runtime.maxMemory();
273
}
274
275
private double getCurrentQps() {
276
// Implementation to calculate QPS
277
return Math.random() * 1000; // Example
278
}
279
}
280
```
281
282
## Monitoring and Observability Integration
283
284
```java
285
public class ObservableServer {
286
287
public static void main(String[] args) throws Exception {
288
// Server with comprehensive observability
289
Server server = ServerBuilder.forPort(8080)
290
// Standard admin services
291
.addServices(AdminInterface.getStandardServices())
292
293
// Business services
294
.addService(new UserService())
295
296
// Add interceptors for detailed observability
297
.intercept(new LoggingInterceptor())
298
.intercept(new TracingInterceptor())
299
.intercept(new MetricsInterceptor())
300
.build();
301
302
server.start();
303
304
// Start admin service monitoring
305
startAdminServiceMonitoring(server.getPort());
306
307
server.awaitTermination();
308
}
309
310
private static void startAdminServiceMonitoring(int port) {
311
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
312
313
scheduler.scheduleAtFixedRate(() -> {
314
try {
315
// Monitor channelz data
316
monitorChannelzData(port);
317
318
// Monitor health status
319
monitorHealthStatus(port);
320
321
} catch (Exception e) {
322
System.err.println("Monitoring error: " + e.getMessage());
323
}
324
}, 60, 60, TimeUnit.SECONDS); // Monitor every minute
325
}
326
327
private static void monitorChannelzData(int port) {
328
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", port)
329
.usePlaintext()
330
.build();
331
332
try {
333
ChannelzGrpc.ChannelzBlockingStub channelzStub =
334
ChannelzGrpc.newBlockingStub(channel);
335
336
GetServersResponse response = channelzStub.getServers(
337
GetServersRequest.newBuilder().setMaxResults(10).build());
338
339
response.getServerList().forEach(server -> {
340
ServerData data = server.getData();
341
System.out.printf("Server calls: started=%d, succeeded=%d, failed=%d%n",
342
data.getCallsStarted(),
343
data.getCallsSucceeded(),
344
data.getCallsFailed());
345
});
346
347
} finally {
348
channel.shutdown();
349
}
350
}
351
352
private static void monitorHealthStatus(int port) {
353
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", port)
354
.usePlaintext()
355
.build();
356
357
try {
358
HealthGrpc.HealthBlockingStub healthStub =
359
HealthGrpc.newBlockingStub(channel);
360
361
HealthCheckResponse response = healthStub.check(
362
HealthCheckRequest.newBuilder().setService("").build());
363
364
System.out.println("Overall server health: " + response.getStatus());
365
366
} finally {
367
channel.shutdown();
368
}
369
}
370
}
371
```
372
373
## Security Considerations
374
375
Admin services expose operational data and should be secured appropriately:
376
377
```java
378
public class SecureAdminServer {
379
380
public static void main(String[] args) throws Exception {
381
// Check if admin services should be enabled
382
boolean enableAdminServices = Boolean.parseBoolean(
383
System.getProperty("enable.admin.services", "false"));
384
385
ServerBuilder<?> serverBuilder = ServerBuilder.forPort(8080);
386
387
if (enableAdminServices) {
388
System.out.println("Admin services enabled - ensure proper network security");
389
serverBuilder.addServices(AdminInterface.getStandardServices());
390
} else {
391
System.out.println("Admin services disabled for security");
392
}
393
394
Server server = serverBuilder
395
.addService(new UserService())
396
.build();
397
398
server.start();
399
server.awaitTermination();
400
}
401
}
402
403
// Alternative: Admin services on separate port
404
public class SeparateAdminPortServer {
405
406
public static void main(String[] args) throws Exception {
407
// Main business server
408
Server businessServer = ServerBuilder.forPort(8080)
409
.addService(new UserService())
410
.addService(new OrderService())
411
.build();
412
413
// Admin server on separate port (can be firewalled differently)
414
Server adminServer = ServerBuilder.forPort(9090)
415
.addServices(AdminInterface.getStandardServices())
416
.build();
417
418
businessServer.start();
419
adminServer.start();
420
421
System.out.println("Business server on port 8080");
422
System.out.println("Admin server on port 9090");
423
424
// Wait for both servers
425
businessServer.awaitTermination();
426
adminServer.awaitTermination();
427
}
428
}
429
```