mirror of
https://github.com/wassname/ray.git
synced 2026-09-10 12:38:43 +08:00
[Serve] Migrate from Flask.Request to Starlette Request (#12852)
This commit is contained in:
+15
-22
@@ -117,7 +117,7 @@ policies <serve-split-traffic>`, finding the next available replica, and
|
||||
batching requests together.
|
||||
|
||||
When the request arrives in the model, you can access the data similarly to how
|
||||
you would with HTTP request. Here are some examples how ServeRequest mirrors Flask.Request:
|
||||
you would with HTTP request. Here are some examples how ServeRequest mirrors Starlette.Request:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
@@ -125,25 +125,25 @@ you would with HTTP request. Here are some examples how ServeRequest mirrors Fla
|
||||
* - HTTP
|
||||
- ServeHandle
|
||||
- | Request
|
||||
| (Flask.Request and ServeRequest)
|
||||
| (Starlette.Request and ServeRequest)
|
||||
* - ``requests.get(..., headers={...})``
|
||||
- ``handle.options(http_headers={...})``
|
||||
- ``request.headers``
|
||||
* - ``requests.post(...)``
|
||||
- ``handle.options(http_method="POST")``
|
||||
- ``requests.method``
|
||||
* - ``request.get(..., json={...})``
|
||||
- ``request.method``
|
||||
* - ``requests.get(..., json={...})``
|
||||
- ``handle.remote({...})``
|
||||
- ``request.json``
|
||||
* - ``request.get(..., form={...})``
|
||||
- ``await request.json()``
|
||||
* - ``requests.get(..., form={...})``
|
||||
- ``handle.remote({...})``
|
||||
- ``request.form``
|
||||
* - ``request.get(..., params={"a":"b"})``
|
||||
- ``await request.form()``
|
||||
* - ``requests.get(..., params={"a":"b"})``
|
||||
- ``handle.remote(a="b")``
|
||||
- ``request.args``
|
||||
* - ``request.get(..., data="long string")``
|
||||
- ``request.query_params``
|
||||
* - ``requests.get(..., data="long string")``
|
||||
- ``handle.remote("long string")``
|
||||
- ``request.data``
|
||||
- ``await request.body()``
|
||||
* - ``N/A``
|
||||
- ``handle.remote(python_object)``
|
||||
- ``request.data``
|
||||
@@ -157,9 +157,9 @@ you would with HTTP request. Here are some examples how ServeRequest mirrors Fla
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import flask
|
||||
import starlette.requests
|
||||
|
||||
if isinstance(request, flask.Request):
|
||||
if isinstance(request, starlette.requests.Request):
|
||||
print("Request coming from web!")
|
||||
elif isinstance(request, ServeRequest):
|
||||
print("Request coming from Python!")
|
||||
@@ -170,10 +170,10 @@ you would with HTTP request. Here are some examples how ServeRequest mirrors Fla
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
handle.remote(flask_request)
|
||||
handle.remote(starlette_request)
|
||||
|
||||
In this case, Serve will `not` wrap it in ServeRequest. You can directly
|
||||
process the request as a ``flask.Request``.
|
||||
process the request as a ``starlette.requests.Request``.
|
||||
|
||||
How fast is Ray Serve?
|
||||
----------------------
|
||||
@@ -187,13 +187,6 @@ You can checkout our `microbenchmark instruction <https://github.com/ray-project
|
||||
to benchmark on your hardware.
|
||||
|
||||
|
||||
Does Ray Serve use Flask?
|
||||
-------------------------
|
||||
Flask is only used as a web request object for servable to consume the data.
|
||||
We actually use the fastest Python web server: `Uvicorn <https://www.uvicorn.org/>`_ as our web server,
|
||||
alongside with the power of Python asyncio.
|
||||
**Flask is ONLY the request object that we are using, Uvicorn (not flask) provides the webserver.**
|
||||
|
||||
Can I use asyncio along with Ray Serve?
|
||||
---------------------------------------
|
||||
Yes! You can make your servable methods ``async def`` and Serve will run them
|
||||
|
||||
@@ -33,6 +33,9 @@ Since Serve is built on Ray, it also allows you to scale to many machines, in yo
|
||||
If you want to try out Serve, join our `community slack <https://forms.gle/9TSdDYUgxYs8SA9e8>`_
|
||||
and discuss in the #serve channel.
|
||||
|
||||
.. note::
|
||||
Starting with Ray version 1.3.0, Ray Serve backends must take in a Starlette Request object instead of a Flask Request object.
|
||||
See the `migration guide <https://docs.google.com/document/d/1CG4y5WTTc4G_MRQGyjnb_eZ7GK3G9dUX6TNLKLnKRAc/edit?usp=sharing>`_ for details.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
@@ -19,10 +19,8 @@ Backends
|
||||
Backends define the implementation of your business logic or models that will handle requests when queries come in to :ref:`serve-endpoint`.
|
||||
In order to support seamless scalability backends can have many replicas, which are individual processes running in the Ray cluster to handle requests.
|
||||
To define a backend, first you must define the "handler" or the business logic you'd like to respond with.
|
||||
The handler should take as input a `Flask Request object <https://flask.palletsprojects.com/en/1.1.x/api/?highlight=request#flask.Request>`_.
|
||||
The handler should return any JSON-serializable object as output. For a more customizable response type, the handler may return a
|
||||
The handler should take as input a `Starlette Request object <https://www.starlette.io/requests/>`_ and return any JSON-serializable object as output. For a more customizable response type, the handler may return a
|
||||
`Starlette Response object <https://www.starlette.io/responses/>`_.
|
||||
In the future, Ray Serve will support `Starlette Request objects <https://www.starlette.io/requests/>`_ as input as well.
|
||||
|
||||
A backend is defined using :mod:`client.create_backend <ray.serve.api.Client.create_backend>`, and the implementation can be defined as either a function or a class.
|
||||
Use a function when your response is stateless and a class when you might need to maintain some state (like a model).
|
||||
@@ -32,7 +30,7 @@ A backend consists of a number of *replicas*, which are individual copies of the
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def handle_request(flask_request):
|
||||
def handle_request(starlette_request):
|
||||
return "hello world"
|
||||
|
||||
class RequestHandler:
|
||||
@@ -40,7 +38,7 @@ A backend consists of a number of *replicas*, which are individual copies of the
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
|
||||
def __call__(self, flask_request):
|
||||
def __call__(self, starlette_request):
|
||||
return self.msg
|
||||
|
||||
client.create_backend("simple_backend", handle_request)
|
||||
|
||||
@@ -23,7 +23,7 @@ Handle API
|
||||
:members: remote, options
|
||||
|
||||
When calling from Python, the backend implementation will receive ``ServeRequest``
|
||||
objects instead of Flask requests.
|
||||
objects instead of Starlette requests.
|
||||
|
||||
.. autoclass:: ray.serve.utils.ServeRequest
|
||||
:members:
|
||||
|
||||
@@ -30,13 +30,13 @@ You can use the ``@serve.accept_batch`` decorator to annotate a function or a cl
|
||||
This annotation is needed because batched backends have different APIs compared
|
||||
to single request backends. In a batched backend, the inputs are a list of values.
|
||||
|
||||
For single query backend, the input type is a single Flask request or
|
||||
For single query backend, the input type is a single Starlette request or
|
||||
:mod:`ServeRequest <ray.serve.utils.ServeRequest>`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def single_request(
|
||||
request: Union[Flask.Request, ServeRequest],
|
||||
request: Union[starlette.requests.Request, ServeRequest],
|
||||
):
|
||||
pass
|
||||
|
||||
@@ -47,7 +47,7 @@ types:
|
||||
|
||||
@serve.accept_batch
|
||||
def batched_request(
|
||||
request: List[Union[Flask.Request, ServeRequest]],
|
||||
request: List[Union[starlette.requests.Request, ServeRequest]],
|
||||
):
|
||||
pass
|
||||
|
||||
@@ -84,8 +84,8 @@ Ray Serve was able to evaluate them in batches.
|
||||
|
||||
What if you want to evaluate a whole batch in Python? Ray Serve allows you to send
|
||||
queries via the Python API. A batch of queries can either come from the web server
|
||||
or the Python API. Requests coming from the Python API will have the similar API
|
||||
as Flask.Request. See more on the API :ref:`here<serve-handle-explainer>`.
|
||||
or the Python API. Requests coming from the Python API will have a similar API
|
||||
to Starlette Request. See more on the API :ref:`here<serve-handle-explainer>`.
|
||||
|
||||
.. literalinclude:: ../../../../python/ray/serve/examples/doc/tutorial_batch.py
|
||||
:start-after: __doc_define_servable_v1_begin__
|
||||
|
||||
Reference in New Issue
Block a user