-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgrpc_server_4_epoll.zig
More file actions
78 lines (69 loc) · 2.53 KB
/
Copy pathgrpc_server_4_epoll.zig
File metadata and controls
78 lines (69 loc) · 2.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! gRPC h2c server example: EPOLL dispatch model. Linux-only.
//! Port: 9035
//!
//! EPOLL for gRPC uses a single epoll event loop to accept connections and
//! hands each fd to a worker pool. Workers run the full gRPC connection loop
//! (HTTP/2 is stateful: HPACK table, stream state, flow control), so idle
//! keep-alive connections still hold a thread. The benefit over POOL is a
//! single-threaded accept loop rather than N accept threads.
//! Use POOL or ASYNC on non-Linux platforms.
//!
//! Run:
//! zig build example-grpc_server_4_epoll
//! ./zig-out/bin/example-grpc_server_4_epoll
//!
//! Test with grpcurl (requires grpcurl installed):
//! grpcurl -proto examples/protobuf/helloworld.proto -plaintext \
//! -d '{"name":"world"}' 127.0.0.1:9035 helloworld.Greeter/SayHello
//!
//! Benchmark with h2load (requires nghttp2):
//! h2load -n 999999 -c 256 -t 4 -D 10 \
//! --header 'content-type: application/grpc+proto' \
//! --header 'te: trailers' \
//! --data examples/grpc_hello_req.bin \
//! http://127.0.0.1:9035/helloworld.Greeter/SayHello
//!
//! Benchmark with ghz (requires ghz):
//! ghz --insecure \
//! --proto examples/protobuf/helloworld.proto \
//! --call helloworld.Greeter/SayHello \
//! -d '{"name":"world"}' -c 64 -z 10s \
//! 127.0.0.1:9035
const std = @import("std");
const zix = @import("zix");
fn sayHelloHandler(headers: []const zix.Http2.Header, ctx: *zix.Grpc.Context) void {
_ = headers;
const msg = ctx.recvMessage() orelse {
ctx.finish(zix.Grpc.Status.INVALID_ARGUMENT, "empty request");
return;
};
var out: [256]u8 = undefined;
const resp = std.fmt.bufPrint(&out, "Hello, {s}!", .{msg}) catch "Hello!";
ctx.sendMessage("application/grpc+proto", resp);
ctx.finish(zix.Grpc.Status.OK, "");
}
fn echoHandler(headers: []const zix.Http2.Header, ctx: *zix.Grpc.Context) void {
_ = headers;
while (ctx.recvMessage()) |msg| {
ctx.sendMessage("application/grpc+proto", msg);
}
ctx.finish(zix.Grpc.Status.OK, "");
}
const Routes = [_]zix.Grpc.Route{
.{ .path = "/helloworld.Greeter/SayHello", .handler = sayHelloHandler },
.{ .path = "/helloworld.Greeter/Echo", .handler = echoHandler, .is_server_streaming = true },
};
pub fn main(process: std.process.Init) !void {
var server = zix.Grpc.Server.init(
&Routes,
.{
.io = process.io,
.ip = "127.0.0.1",
.port = 9035,
.dispatch_model = .EPOLL,
.pool_size = 0,
},
);
defer server.deinit();
try server.run();
}