code: def start_grpc_server(
      bento_identifier: str,
      runner_map: dict[str, str],
      working_dir: str,
      port: int = Provide[BentoMLContainer.grpc.port],
      host: str = Provide[BentoMLContainer.grpc.host],
      backlog: int = Provide[
          BentoMLContainer.api_server_config.backlog
      ],
      api_workers: int = Provide[BentoMLContainer.api_server_workers],
      reflection: bool = Provide[
          BentoMLContainer.grpc.reflection.enabled
      ],
      channelz: bool = Provide[BentoMLContainer.grpc.channelz.enabled],
      max_concurrent_streams: int
      | None = Provide[BentoMLContainer.grpc.max_concurrent_streams],
      ssl_certfile: str | None = Provide[BentoMLContainer.ssl.certfile],
      ssl_keyfile: str | None = Provide[BentoMLContainer.ssl.keyfile],
      ssl_ca_certs: str | None = Provide[BentoMLContainer.ssl.ca_certs],
      protocol_version: str = LATEST_PROTOCOL_VERSION,
  ) -> None:
      from .serve import ensure_prometheus_dir
  
      prometheus_dir = ensure_prometheus_dir()
  
      from circus.sockets import CircusSocket
      from circus.watcher import Watcher
  
      from bentoml import load
  
      from ._internal.utils import reserve_free_port
      from ._internal.utils.analytics import track_serve
      from ._internal.utils.circus import create_standalone_arbiter
      from .serve import PROMETHEUS_MESSAGE
      from .serve import PROMETHEUS_SERVER_NAME
      from .serve import construct_ssl_args
      from .serve import create_watcher
  
      working_dir = os.path.realpath(os.path.expanduser(working_dir))
      svc = load(
          bento_identifier,
          working_dir=working_dir,
          standalone_load=True,
      )
      runner_requirements = {runner.name for runner in svc.runners}
      if not runner_requirements.issubset(set(runner_map)):
          raise ValueError(
              f"{bento_identifier} requires runners {runner_requirements}, but only {set(runner_map)} are provided."
          )
      watchers: list[Watcher] = []
      circus_socket_map: dict[str, CircusSocket] = {}
      logger.debug("Runner map: %s", runner_map)
      ssl_args = construct_ssl_args(
          ssl_certfile=ssl_certfile,
          ssl_keyfile=ssl_keyfile,
          ssl_ca_certs=ssl_ca_certs,
      )
      scheme = "https" if BentoMLContainer.ssl.enabled.get() else "http"
      with contextlib.ExitStack() as port_stack:
          api_port = port_stack.enter_context(
              reserve_free_port(
                  host=host, port=port, enable_so_reuseport=True
              )
          )
  
          args = [
              "-m",
              SCRIPT_GRPC_API_SERVER,
              bento_identifier,
              "--host",
              host,
              "--port",
              str(api_port),
              "--runner-map",
              json.dumps(runner_map),
              "--working-dir",
              working_dir,
              "--prometheus-dir",
              prometheus_dir,
              "--worker-id",
              "$(CIRCUS.WID)",
              *ssl_args,
              "--protocol-version",
              protocol_version,
          ]
          if reflection:
              args.append("--enable-reflection")
          if channelz:
              args.append("--enable-channelz")
          if max_concurrent_streams:
              args.extend(
                  [
                      "--max-concurrent-streams",
                      str(max_concurrent_streams),
                  ]
              )
  
          watchers.append(
              create_watcher(
                  name="grpc_api_server",
                  args=args,
                  use_sockets=False,
                  working_dir=working_dir,
                  numprocesses=api_workers,
              )
          )
  
      if BentoMLContainer.api_server_config.metrics.enabled.get():
          metrics_host = BentoMLContainer.grpc.metrics.host.get()
          metrics_port = BentoMLContainer.grpc.metrics.port.get()
  
          circus_socket_map[PROMETHEUS_SERVER_NAME] = CircusSocket(
              name=PROMETHEUS_SERVER_NAME,
              host=metrics_host,
              port=metrics_port,
              backlog=backlog,
          )
  
          watchers.append(
              create_watcher(
                  name="prom_server",
                  args=[
                      "-m",
                      SCRIPT_GRPC_PROMETHEUS_SERVER,
                      "--fd",
                      f"$(circus.sockets.{PROMETHEUS_SERVER_NAME})",
                      "--prometheus-dir",
                      prometheus_dir,
                      "--backlog",
                      f"{backlog}",
                  ],
                  working_dir=working_dir,
                  numprocesses=1,
                  singleton=True,
              )
          )
  
          logger.info(
              PROMETHEUS_MESSAGE,
              "gRPC",
              bento_identifier,
              f"http://{metrics_host}:{metrics_port}",
          )
      arbiter = create_standalone_arbiter(
          watchers=watchers, sockets=list(circus_socket_map.values())
      )
      with track_serve(
          svc, production=True, component=API_SERVER, serve_kind="grpc"
      ):
          arbiter.start(
              cb=lambda _: logger.info(  # type: ignore
                  'Starting bare %s BentoServer from "%s" running on %s://%s:%d (Press CTRL+C to quit)',
                  "gRPC",
                  bento_identifier,
                  scheme,
                  host,
                  port,
              ),
          )
  
file_path: BentoML/grpc-client/bentoml/start.py
imports: from __future__ import annotations
  import contextlib
  import json
  import logging
  import os
  from simple_di import Provide
  from simple_di import inject
  from ._internal.configuration.containers import BentoMLContainer
  from ._internal.runner.runner import Runner
  from .grpc.utils import LATEST_PROTOCOL_VERSION
label_desc: Use image node_id 3 for calling a global function with example usage: start_grpc_server(bento_identifier, runner_map, working_dir, port, host, backlog, api_workers, reflection, channelz, max_concurrent_streams, ssl_certfile, ssl_keyfile, ssl_ca_certs, protocol_version) without return types