Giter Site home page Giter Site logo

Comments (4)

edoakes avatar edoakes commented on May 8, 2024 1

@edoakes question: above I've only described how it would work for serve.run. I haven't looked at the code yet, but I assume that it'll need be to allowed in more places, like from a static Serve config file?

We can do the same in the config file:

   route_prefix: null

from ray.

JoshKarpel avatar JoshKarpel commented on May 8, 2024

@edoakes question: above I've only described how it would work for serve.run. I haven't looked at the code yet, but I assume that it'll need be to allowed in more places, like from a static Serve config file?

from ray.

JoshKarpel avatar JoshKarpel commented on May 8, 2024

Great news! As far as I can tell, this actually already works, and is sort-of documented here:

"and app information has not yet fully propagated in the backend; or "
"if the user explicitly set the prefix to `None`, so the application isn't "
"exposed over HTTP. Routing is done based on longest-prefix match, so if "

And indeed, passing route_prefix=None to serve.run or setting route_prefix: null in a Serve config file does the right thing:

import time

import requests
from ray import serve

@serve.deployment()
class D:
    async def __call__(self, *args, **kwargs):
        return "Hello, world!"


d = D.bind()

if __name__ == "__main__":
    serve.run(d, route_prefix=None)
    time.sleep(5)
    print(requests.get("http://localhost:8000/-/routes").json())  # {} 
    print('sleeping...')
    time.sleep(100000)
proxy_location: EveryNode

http_options:
  host: 0.0.0.0
  port: 8000

applications:
  - name: d
    route_prefix: null
    import_path: serve:d

It looks like the join point between the controller state and what the proxy ends up seeing is

if deployment_info.route_prefix is not None:
config = deployment_info.deployment_config
self._endpoint_state.update_endpoint(
deployment_id,
# The current meaning of the "is_cross_language" field is ambiguous.
# We will work on optimizing and removing this field in the future.
# Instead of using the "is_cross_language" field, we will directly
# compare if the replica is Python, which will assist the Python
# router in determining if the replica invocation is a cross-language
# operation.
EndpointInfo(
route=deployment_info.route_prefix,
app_is_cross_language=config.deployment_language
!= DeploymentLanguage.PYTHON,
),
)
else:
self._endpoint_state.delete_endpoint(deployment_id)
, and it implicitly handles deployments without route_prefixes, not caring whether they are ingress deployments or not.

Perhaps this was done for gRPC support? So that gRPC ingress didn't also imply an HTTP ingress route?

`route_prefix` is still a required field as of Ray 2.7.0 due to a shared code path with
HTTP. Future releases will make it optional for gRPC.

It's even tested!

def test_deployment_without_route(serve_instance):
@serve.deployment(route_prefix=None)
class D:
def __call__(self, *args):
return "1"
serve.run(D.bind(), route_prefix=None)
routes = requests.get("http://localhost:8000/-/routes").json()
assert len(routes) == 0
# make sure the deployment is not exposed under the default route
r = requests.get("http://localhost:8000/")
assert r.status_code == 404

The main thing that's wrong seems to be the typing of the route_prefix argument - I'll take care of that, and poke around for any docs adjacent to the route_prefix that should discuss this.

from ray.

edoakes avatar edoakes commented on May 8, 2024

Great news! As far as I can tell, this actually already works, and is sort-of documented here:

"and app information has not yet fully propagated in the backend; or "
"if the user explicitly set the prefix to `None`, so the application isn't "
"exposed over HTTP. Routing is done based on longest-prefix match, so if "

And indeed, passing route_prefix=None to serve.run or setting route_prefix: null in a Serve config file does the right thing:

import time

import requests
from ray import serve

@serve.deployment()
class D:
    async def __call__(self, *args, **kwargs):
        return "Hello, world!"


d = D.bind()

if __name__ == "__main__":
    serve.run(d, route_prefix=None)
    time.sleep(5)
    print(requests.get("http://localhost:8000/-/routes").json())  # {} 
    print('sleeping...')
    time.sleep(100000)
proxy_location: EveryNode

http_options:
  host: 0.0.0.0
  port: 8000

applications:
  - name: d
    route_prefix: null
    import_path: serve:d

It looks like the join point between the controller state and what the proxy ends up seeing is

if deployment_info.route_prefix is not None:
config = deployment_info.deployment_config
self._endpoint_state.update_endpoint(
deployment_id,
# The current meaning of the "is_cross_language" field is ambiguous.
# We will work on optimizing and removing this field in the future.
# Instead of using the "is_cross_language" field, we will directly
# compare if the replica is Python, which will assist the Python
# router in determining if the replica invocation is a cross-language
# operation.
EndpointInfo(
route=deployment_info.route_prefix,
app_is_cross_language=config.deployment_language
!= DeploymentLanguage.PYTHON,
),
)
else:
self._endpoint_state.delete_endpoint(deployment_id)

, and it implicitly handles deployments without route_prefixes, not caring whether they are ingress deployments for not.
Perhaps this was done for gRPC support? So that gRPC ingress didn't also imply an HTTP ingress route?

`route_prefix` is still a required field as of Ray 2.7.0 due to a shared code path with
HTTP. Future releases will make it optional for gRPC.

It's even tested!

def test_deployment_without_route(serve_instance):
@serve.deployment(route_prefix=None)
class D:
def __call__(self, *args):
return "1"
serve.run(D.bind(), route_prefix=None)
routes = requests.get("http://localhost:8000/-/routes").json()
assert len(routes) == 0
# make sure the deployment is not exposed under the default route
r = requests.get("http://localhost:8000/")
assert r.status_code == 404

The main thing that's wrong seems to be the typing of the route_prefix argument - I'll take care of that, and poke around for any docs adjacent to the route_prefix that should discuss this.

Ah yes I believe you're right, I vaguely recall a conversation with @GeneDer about this when he was adding gRPC support :)

Let's clean up the API ref and document this then!

from ray.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.