Skip to content

Commit

Permalink
feat: Add gunicorn for serve with multiprocess (feast-dev#3636)
Browse files Browse the repository at this point in the history
* feat: Add gunicorn for serve with multiprocess

Signed-off-by: phil.park <bakjeeone@hotmail.com>

* feat: Add gunicorn to requirements for ci

Signed-off-by: phil.park <bakjeeone@hotmail.com>

---------

Signed-off-by: phil.park <bakjeeone@hotmail.com>
  • Loading branch information
phil-park authored Jun 5, 2023
1 parent bf740d2 commit 4de7faf
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 10 deletions.
27 changes: 26 additions & 1 deletion sdk/python/feast/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,21 @@ def init_command(project_directory, minimal: bool, template: str):
show_default=True,
help="Disable logging served features",
)
@click.option(
"--workers",
"-w",
type=click.INT,
default=1,
show_default=True,
help="Number of worker",
)
@click.option(
"--keep-alive-timeout",
type=click.INT,
default=5,
show_default=True,
help="Timeout for keep alive",
)
@click.pass_context
def serve_command(
ctx: click.Context,
Expand All @@ -657,11 +672,21 @@ def serve_command(
type_: str,
no_access_log: bool,
no_feature_log: bool,
workers: int,
keep_alive_timeout: int,
):
"""Start a feature server locally on a given port."""
store = create_feature_store(ctx)

store.serve(host, port, type_, no_access_log, no_feature_log)
store.serve(
host=host,
port=port,
type_=type_,
no_access_log=no_access_log,
no_feature_log=no_feature_log,
workers=workers,
keep_alive_timeout=keep_alive_timeout,
)


@cli.command("serve_transformations")
Expand Down
35 changes: 31 additions & 4 deletions sdk/python/feast/feature_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import traceback
import warnings

import gunicorn.app.base
import pandas as pd
import uvicorn
from fastapi import FastAPI, HTTPException, Request, Response, status
from fastapi.logger import logger
from fastapi.params import Depends
Expand Down Expand Up @@ -137,8 +137,35 @@ def health():
return app


class FeastServeApplication(gunicorn.app.base.BaseApplication):
def __init__(self, store: "feast.FeatureStore", **options):
self._app = get_app(store=store)
self._options = options
super().__init__()

def load_config(self):
for key, value in self._options.items():
if key.lower() in self.cfg.settings and value is not None:
self.cfg.set(key.lower(), value)

self.cfg.set("worker_class", "uvicorn.workers.UvicornWorker")

def load(self):
return self._app


def start_server(
store: "feast.FeatureStore", host: str, port: int, no_access_log: bool
store: "feast.FeatureStore",
host: str,
port: int,
no_access_log: bool,
workers: int,
keep_alive_timeout: int,
):
app = get_app(store)
uvicorn.run(app, host=host, port=port, access_log=(not no_access_log))
FeastServeApplication(
store=store,
bind=f"{host}:{port}",
accesslog=None if no_access_log else "-",
workers=workers,
keepalive=keep_alive_timeout,
).run()
12 changes: 10 additions & 2 deletions sdk/python/feast/feature_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -2152,7 +2152,6 @@ def _get_feature_views_to_use(
allow_cache=False,
hide_dummy_entity: bool = True,
) -> Tuple[List[FeatureView], List[RequestFeatureView], List[OnDemandFeatureView]]:

fvs = {
fv.name: fv
for fv in [
Expand Down Expand Up @@ -2223,6 +2222,8 @@ def serve(
type_: str,
no_access_log: bool,
no_feature_log: bool,
workers: int,
keep_alive_timeout: int,
) -> None:
"""Start the feature consumption server locally on a given port."""
type_ = type_.lower()
Expand All @@ -2231,7 +2232,14 @@ def serve(
f"Python server only supports 'http'. Got '{type_}' instead."
)
# Start the python server
feature_server.start_server(self, host, port, no_access_log)
feature_server.start_server(
self,
host=host,
port=port,
no_access_log=no_access_log,
workers=workers,
keep_alive_timeout=keep_alive_timeout,
)

@log_exceptions_and_usage
def get_feature_server_endpoint(self) -> Optional[str]:
Expand Down
2 changes: 2 additions & 0 deletions sdk/python/requirements/py3.10-ci-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ grpcio-testing==1.54.2
# via feast (setup.py)
grpcio-tools==1.54.2
# via feast (setup.py)
gunicorn==20.1.0
# via feast (setup.py)
h11==0.14.0
# via
# httpcore
Expand Down
2 changes: 2 additions & 0 deletions sdk/python/requirements/py3.10-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ grpcio==1.54.2
# grpcio-reflection
grpcio-reflection==1.54.2
# via feast (setup.py)
gunicorn==20.1.0
# via feast (setup.py)
h11==0.14.0
# via
# httpcore
Expand Down
2 changes: 2 additions & 0 deletions sdk/python/requirements/py3.8-ci-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ grpcio-testing==1.54.2
# via feast (setup.py)
grpcio-tools==1.54.2
# via feast (setup.py)
gunicorn==20.1.0
# via feast (setup.py)
h11==0.14.0
# via
# httpcore
Expand Down
2 changes: 2 additions & 0 deletions sdk/python/requirements/py3.8-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ grpcio==1.54.2
# grpcio-reflection
grpcio-reflection==1.54.2
# via feast (setup.py)
gunicorn==20.1.0
# via feast (setup.py)
h11==0.14.0
# via
# httpcore
Expand Down
2 changes: 2 additions & 0 deletions sdk/python/requirements/py3.9-ci-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ grpcio-testing==1.54.2
# via feast (setup.py)
grpcio-tools==1.54.2
# via feast (setup.py)
gunicorn==20.1.0
# via feast (setup.py)
h11==0.14.0
# via
# httpcore
Expand Down
2 changes: 2 additions & 0 deletions sdk/python/requirements/py3.9-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ grpcio==1.54.2
# grpcio-reflection
grpcio-reflection==1.54.2
# via feast (setup.py)
gunicorn==20.1.0
# via feast (setup.py)
h11==0.14.0
# via
# httpcore
Expand Down
5 changes: 2 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"typeguard==2.13.3",
"fastapi>=0.68.0,<1",
"uvicorn[standard]>=0.14.0,<1",
"gunicorn",
"dask>=2021.1.0",
"bowler", # Needed for automatic repo upgrades
# FastAPI does not correctly pull starlette dependency on httpx see thread(https://github.com/tiangolo/fastapi/issues/5656).
Expand Down Expand Up @@ -103,9 +104,7 @@
"pyspark>=3.0.0,<4",
]

TRINO_REQUIRED = [
"trino>=0.305.0,<0.400.0", "regex"
]
TRINO_REQUIRED = ["trino>=0.305.0,<0.400.0", "regex"]

POSTGRES_REQUIRED = [
"psycopg2-binary>=2.8.3,<3",
Expand Down

0 comments on commit 4de7faf

Please sign in to comment.