[Frontend] Move grpc_server to launchers. (#56746)
Signed-off-by: wang.yuqi <yuqi.wang@daocloud.io>
wang.yuqi committed
Sep 14, 2026 at 13:03 UTC
67111973eeb104e83bc6707a2d0f139737b711a0
4 files changed
+218
-191
tests/entrypoints/launchers/test_grpc_health.py
renamed
vllm/entrypoints/cli/serve.py
+1
-1
@@ -54,7 +54,7 @@ class ServeSubcommand(CLISubcommand):
54
args.model = args.model_tag
55
56
if getattr(args, "grpc", False):
57
- from vllm.entrypoints.grpc_server import serve_grpc
57
+ from vllm.entrypoints.launchers.grpc_server import serve_grpc
58
59
uvloop.run(serve_grpc(args))
60
return
vllm/entrypoints/grpc_server.py
+17
-190
@@ -1,200 +1,27 @@
1
-#!/usr/bin/env python3
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
4
-# mypy: ignore-errors
5
-"""
6
-vLLM gRPC Server
3
+import warnings
4
8
-Starts a gRPC server backed by AsyncLLM, using the VllmEngineServicer
9
-from the smg-grpc-servicer package.
5
+from vllm.entrypoints.launchers.grpc_server import main, serve_grpc
6
11
-Usage:
12
- python -m vllm.entrypoints.grpc_server --model <model_path>
7
+warnings.warn(
8
+ "`vllm.entrypoints.grpc_server is deprecated and will likely be "
9
+ "unsupported in a future version. Use the corresponding function from "
10
+ "`vllm.entrypoints.launchers.grpc_server` instead.",
11
+ DeprecationWarning,
12
+ stacklevel=1,
13
+)
14
14
-Example:
15
- python -m vllm.entrypoints.grpc_server \
16
- --model meta-llama/Llama-2-7b-hf \
17
- --host 0.0.0.0 \
18
- --port 50051
19
-"""
15
+__all__ = ["main", "serve_grpc"]
16
21
-import argparse
22
-import asyncio
23
-import signal
24
-import sys
25
-import time
17
27
-try:
28
- import grpc
29
- from grpc_health.v1 import health_pb2_grpc
30
- from grpc_reflection.v1alpha import reflection
31
- from smg_grpc_proto import vllm_engine_pb2, vllm_engine_pb2_grpc
32
- from smg_grpc_servicer.vllm.health_servicer import VllmHealthServicer
33
- from smg_grpc_servicer.vllm.servicer import VllmEngineServicer
34
-except ImportError as e:
35
- raise ImportError(
36
- "gRPC mode requires smg-grpc-servicer. "
37
- "If not installed, run: pip install vllm[grpc]. "
38
- "If already installed, there may be a broken import due to a "
39
- "version mismatch — see the chained exception above for details."
40
- ) from e
41
-
42
-import uvloop
43
-
44
-from vllm import envs
45
-from vllm.engine.arg_utils import AsyncEngineArgs
46
-from vllm.entrypoints.serve.utils.api_utils import log_version_and_model
47
-from vllm.logger import init_logger
48
-from vllm.usage.usage_lib import UsageContext
49
-from vllm.utils.argparse_utils import FlexibleArgumentParser
50
-from vllm.v1.engine.async_llm import AsyncLLM
51
-from vllm.version import __version__ as VLLM_VERSION
52
-
53
-logger = init_logger(__name__)
54
-
55
-
56
-async def serve_grpc(args: argparse.Namespace):
57
- """
58
- Main gRPC serving function.
59
-
60
- Args:
61
- args: Parsed command line arguments
62
- """
63
- log_version_and_model(logger, VLLM_VERSION, args.model)
64
- logger.info("vLLM gRPC server args: %s", args)
65
-
66
- start_time = time.time()
67
-
68
- # Create engine args
69
- engine_args = AsyncEngineArgs.from_cli_args(args)
70
-
71
- # Build vLLM config
72
- vllm_config = engine_args.create_engine_config(
73
- usage_context=UsageContext.OPENAI_API_SERVER,
74
- )
75
-
76
- # Create AsyncLLM
77
- async_llm = AsyncLLM.from_vllm_config(
78
- vllm_config=vllm_config,
79
- usage_context=UsageContext.OPENAI_API_SERVER,
80
- enable_log_requests=args.enable_log_requests,
81
- disable_log_stats=args.disable_log_stats,
82
- )
83
-
84
- # Create servicer
85
- servicer = VllmEngineServicer(async_llm, start_time)
86
-
87
- # Create gRPC server
88
- server = grpc.aio.server(
89
- options=[
90
- ("grpc.max_send_message_length", -1),
91
- ("grpc.max_receive_message_length", -1),
92
- # Tolerate client keepalive pings every 10s (default 300s is too
93
- # strict for non-streaming requests where no DATA frames flow
94
- # during generation)
95
- ("grpc.http2.min_recv_ping_interval_without_data_ms", 10000),
96
- ("grpc.keepalive_permit_without_calls", True),
97
- ],
98
- )
99
-
100
- # Add servicer to server
101
- vllm_engine_pb2_grpc.add_VllmEngineServicer_to_server(servicer, server)
102
-
103
- # Add standard gRPC health service for Kubernetes probes
104
- health_servicer = VllmHealthServicer(async_llm)
105
- health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server)
106
-
107
- # Enable reflection for grpcurl and other tools
108
- service_names = (
109
- vllm_engine_pb2.DESCRIPTOR.services_by_name["VllmEngine"].full_name,
110
- "grpc.health.v1.Health",
111
- reflection.SERVICE_NAME,
112
- )
113
- reflection.enable_server_reflection(service_names, server)
114
-
115
- # Bind to address
116
- host = args.host or "0.0.0.0"
117
- address = f"{host}:{args.port}"
118
- server.add_insecure_port(address)
119
-
120
- try:
121
- # Start server
122
- await server.start()
123
- logger.info("vLLM gRPC server started on %s", address)
124
- logger.info("Server is ready to accept requests")
125
-
126
- # Start periodic stats logging (mirrors the HTTP server's lifespan task)
127
- if not args.disable_log_stats:
128
-
129
- async def _force_log():
130
- while True:
131
- await asyncio.sleep(envs.VLLM_LOG_STATS_INTERVAL)
132
- await async_llm.do_log_stats()
133
-
134
- stats_task = asyncio.create_task(_force_log())
135
- else:
136
- stats_task = None
137
-
138
- # Handle shutdown signals
139
- loop = asyncio.get_running_loop()
140
- stop_event = asyncio.Event()
141
-
142
- def signal_handler():
143
- logger.info("Received shutdown signal")
144
- stop_event.set()
145
-
146
- for sig in (signal.SIGTERM, signal.SIGINT):
147
- loop.add_signal_handler(sig, signal_handler)
148
-
149
- try:
150
- await stop_event.wait()
151
- except KeyboardInterrupt:
152
- logger.info("Interrupted by user")
153
- finally:
154
- logger.info("Shutting down vLLM gRPC server...")
155
- if stats_task is not None:
156
- stats_task.cancel()
157
- try:
158
- health_servicer.set_not_serving()
159
- except Exception: # broad: must not prevent server.stop() / shutdown()
160
- logger.warning("Failed to set health status to NOT_SERVING", exc_info=True)
161
- await server.stop(grace=5.0)
162
- logger.info("gRPC server stopped")
163
- async_llm.shutdown()
164
- logger.info("AsyncLLM engine stopped")
165
- logger.info("Shutdown complete")
166
-
167
-
168
-def main():
169
- """Main entry point for python -m vllm.entrypoints.grpc_server."""
170
- parser = FlexibleArgumentParser(
171
- description="vLLM gRPC Server",
172
- )
173
-
174
- # Server args
175
- parser.add_argument(
176
- "--host",
177
- type=str,
178
- default="0.0.0.0",
179
- help="Host to bind gRPC server to",
180
- )
181
- parser.add_argument(
182
- "--port",
183
- type=int,
184
- default=50051,
185
- help="Port to bind gRPC server to",
18
+if __name__ == "__main__":
19
+ warnings.warn(
20
+ "`python -m vllm.entrypoints.grpc_server is deprecated and "
21
+ "will likely be unsupported in a future version. "
22
+ "Please use `vllm serve <model_path> --grpc` instead.",
23
+ DeprecationWarning,
24
+ stacklevel=1,
25
)
187
- parser = AsyncEngineArgs.add_cli_args(parser)
26
189
- args = parser.parse_args()
190
-
191
- # Run server
192
- try:
193
- uvloop.run(serve_grpc(args))
194
- except Exception as e:
195
- logger.exception("Server failed: %s", e)
196
- sys.exit(1)
197
-
198
-
199
-if __name__ == "__main__":
27
main()
vllm/entrypoints/launchers/grpc_server.py
new
+200
@@ -0,0 +1,200 @@
1
+#!/usr/bin/env python3
2
+# SPDX-License-Identifier: Apache-2.0
3
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
4
+# mypy: ignore-errors
5
+"""
6
+vLLM gRPC Server
7
+
8
+Starts a gRPC server backed by AsyncLLM, using the VllmEngineServicer
9
+from the smg-grpc-servicer package.
10
+
11
+Usage:
12
+ python -m vllm.entrypoints.launchers.grpc_server --model <model_path>
13
+
14
+Example:
15
+ python -m vllm.entrypoints.launchers.grpc_server \
16
+ --model meta-llama/Llama-2-7b-hf \
17
+ --host 0.0.0.0 \
18
+ --port 50051
19
+"""
20
+
21
+import argparse
22
+import asyncio
23
+import signal
24
+import sys
25
+import time
26
+
27
+try:
28
+ import grpc
29
+ from grpc_health.v1 import health_pb2_grpc
30
+ from grpc_reflection.v1alpha import reflection
31
+ from smg_grpc_proto import vllm_engine_pb2, vllm_engine_pb2_grpc
32
+ from smg_grpc_servicer.vllm.health_servicer import VllmHealthServicer
33
+ from smg_grpc_servicer.vllm.servicer import VllmEngineServicer
34
+except ImportError as e:
35
+ raise ImportError(
36
+ "gRPC mode requires smg-grpc-servicer. "
37
+ "If not installed, run: pip install vllm[grpc]. "
38
+ "If already installed, there may be a broken import due to a "
39
+ "version mismatch — see the chained exception above for details."
40
+ ) from e
41
+
42
+import uvloop
43
+
44
+from vllm import envs
45
+from vllm.engine.arg_utils import AsyncEngineArgs
46
+from vllm.entrypoints.serve.utils.api_utils import log_version_and_model
47
+from vllm.logger import init_logger
48
+from vllm.usage.usage_lib import UsageContext
49
+from vllm.utils.argparse_utils import FlexibleArgumentParser
50
+from vllm.v1.engine.async_llm import AsyncLLM
51
+from vllm.version import __version__ as VLLM_VERSION
52
+
53
+logger = init_logger(__name__)
54
+
55
+
56
+async def serve_grpc(args: argparse.Namespace):
57
+ """
58
+ Main gRPC serving function.
59
+
60
+ Args:
61
+ args: Parsed command line arguments
62
+ """
63
+ log_version_and_model(logger, VLLM_VERSION, args.model)
64
+ logger.info("vLLM gRPC server args: %s", args)
65
+
66
+ start_time = time.time()
67
+
68
+ # Create engine args
69
+ engine_args = AsyncEngineArgs.from_cli_args(args)
70
+
71
+ # Build vLLM config
72
+ vllm_config = engine_args.create_engine_config(
73
+ usage_context=UsageContext.OPENAI_API_SERVER,
74
+ )
75
+
76
+ # Create AsyncLLM
77
+ async_llm = AsyncLLM.from_vllm_config(
78
+ vllm_config=vllm_config,
79
+ usage_context=UsageContext.OPENAI_API_SERVER,
80
+ enable_log_requests=args.enable_log_requests,
81
+ disable_log_stats=args.disable_log_stats,
82
+ )
83
+
84
+ # Create servicer
85
+ servicer = VllmEngineServicer(async_llm, start_time)
86
+
87
+ # Create gRPC server
88
+ server = grpc.aio.server(
89
+ options=[
90
+ ("grpc.max_send_message_length", -1),
91
+ ("grpc.max_receive_message_length", -1),
92
+ # Tolerate client keepalive pings every 10s (default 300s is too
93
+ # strict for non-streaming requests where no DATA frames flow
94
+ # during generation)
95
+ ("grpc.http2.min_recv_ping_interval_without_data_ms", 10000),
96
+ ("grpc.keepalive_permit_without_calls", True),
97
+ ],
98
+ )
99
+
100
+ # Add servicer to server
101
+ vllm_engine_pb2_grpc.add_VllmEngineServicer_to_server(servicer, server)
102
+
103
+ # Add standard gRPC health service for Kubernetes probes
104
+ health_servicer = VllmHealthServicer(async_llm)
105
+ health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server)
106
+
107
+ # Enable reflection for grpcurl and other tools
108
+ service_names = (
109
+ vllm_engine_pb2.DESCRIPTOR.services_by_name["VllmEngine"].full_name,
110
+ "grpc.health.v1.Health",
111
+ reflection.SERVICE_NAME,
112
+ )
113
+ reflection.enable_server_reflection(service_names, server)
114
+
115
+ # Bind to address
116
+ host = args.host or "0.0.0.0"
117
+ address = f"{host}:{args.port}"
118
+ server.add_insecure_port(address)
119
+
120
+ try:
121
+ # Start server
122
+ await server.start()
123
+ logger.info("vLLM gRPC server started on %s", address)
124
+ logger.info("Server is ready to accept requests")
125
+
126
+ # Start periodic stats logging (mirrors the HTTP server's lifespan task)
127
+ if not args.disable_log_stats:
128
+
129
+ async def _force_log():
130
+ while True:
131
+ await asyncio.sleep(envs.VLLM_LOG_STATS_INTERVAL)
132
+ await async_llm.do_log_stats()
133
+
134
+ stats_task = asyncio.create_task(_force_log())
135
+ else:
136
+ stats_task = None
137
+
138
+ # Handle shutdown signals
139
+ loop = asyncio.get_running_loop()
140
+ stop_event = asyncio.Event()
141
+
142
+ def signal_handler():
143
+ logger.info("Received shutdown signal")
144
+ stop_event.set()
145
+
146
+ for sig in (signal.SIGTERM, signal.SIGINT):
147
+ loop.add_signal_handler(sig, signal_handler)
148
+
149
+ try:
150
+ await stop_event.wait()
151
+ except KeyboardInterrupt:
152
+ logger.info("Interrupted by user")
153
+ finally:
154
+ logger.info("Shutting down vLLM gRPC server...")
155
+ if stats_task is not None:
156
+ stats_task.cancel()
157
+ try:
158
+ health_servicer.set_not_serving()
159
+ except Exception: # broad: must not prevent server.stop() / shutdown()
160
+ logger.warning("Failed to set health status to NOT_SERVING", exc_info=True)
161
+ await server.stop(grace=5.0)
162
+ logger.info("gRPC server stopped")
163
+ async_llm.shutdown()
164
+ logger.info("AsyncLLM engine stopped")
165
+ logger.info("Shutdown complete")
166
+
167
+
168
+def main():
169
+ """Main entry point for python -m vllm.entrypoints.launchers.grpc_server."""
170
+ parser = FlexibleArgumentParser(
171
+ description="vLLM gRPC Server",
172
+ )
173
+
174
+ # Server args
175
+ parser.add_argument(
176
+ "--host",
177
+ type=str,
178
+ default="0.0.0.0",
179
+ help="Host to bind gRPC server to",
180
+ )
181
+ parser.add_argument(
182
+ "--port",
183
+ type=int,
184
+ default=50051,
185
+ help="Port to bind gRPC server to",
186
+ )
187
+ parser = AsyncEngineArgs.add_cli_args(parser)
188
+
189
+ args = parser.parse_args()
190
+
191
+ # Run server
192
+ try:
193
+ uvloop.run(serve_grpc(args))
194
+ except Exception as e:
195
+ logger.exception("Server failed: %s", e)
196
+ sys.exit(1)
197
+
198
+
199
+if __name__ == "__main__":
200
+ main()