cloudflare / pingora

A library for building fast, reliable and evolvable network services.
Apache License 2.0
20.3k stars 1.1k forks source link

Routing to upstreams based on PATH #134

Closed kEpEx closed 3 months ago

kEpEx commented 3 months ago

What is the problem your feature solves, or the need it fulfills?

I am trying to migrate to Pingora from envoy and what I need to route to Upstreams based on part of the URL. I am using route_config matching regex, so would like to see if there is a way to do it.

An example:

domain.com/service1/request/etc -> service1_upstream domain.com/service2/request/etc -> service2_upstream domain.com/service3/request/etc -> service3_upstream

Sorry if this is possible I may need help finding the documentation.

Describe the solution you'd like

  1. A way of adding a filter for each service
  2. Share a listener among multiple services to allow SAMEIP:SAMEPORT/path, SAMEUP: SAMEPORT/path2

Describe alternatives you've considered

I have look into the documentation and the closes that I saw was to use modify_filter ( https://github.com/cloudflare/pingora/blob/main/docs/user_guide/modify_filter.md ) to route, but I will lose all healthcheck and round robin functionality since my upstreams are different services so one being up doesn't mean I can serve the request of other service


async fn upstream_peer(
        &self,
        session: &mut Session,
        _ctx: &mut Self::CTX,
    ) -> Result<Box<HttpPeer>> {
        let addr = if session.req_header().uri.path().starts_with("/service1/") {
            ("service1_upstream", 443)
        } else {
            ("service2_upstream", 443)
        };

        info!("connecting to {addr:?}");

        let peer = Box::new(HttpPeer::new(addr, true, "one.one.one.one".to_string()));
        Ok(peer)
    }

In above example, service1_upstream and service2_upstream has to be part of the same upstream

Additional context

Config I am using on envoy

              - match:
                  safe_regex:
                    regex: "/service1/(.*)"
                route:
                  cluster: service1_cluster
                  regex_rewrite:
                    pattern:
                      regex: "/service1(.*)"
                    substitution: "\\2"
                  auto_host_rewrite: true

              - match:
                  safe_regex:
                    regex: "/service2/(.*)"
                route:
                  cluster: service2_cluster
                  regex_rewrite:
                    pattern:
                      regex: "/service1(.*)"
                    substitution: "\\2"
                  auto_host_rewrite: true
bestgopher commented 3 months ago

Are there any plans to support this?

andrewhavck commented 3 months ago

I need to route to Upstreams based on part of the URL

I have look into the documentation and the closes that I saw was to use modify_filter ( https://github.com/cloudflare/pingora/blob/main/docs/user_guide/modify_filter.md ) to route, but I will lose all healthcheck and round robin functionality since my upstreams are different services so one being up doesn't mean I can serve the request of other service

To be clear is the ask if you can proxy requests to different LoadBalancer clusters based on the downstream request URL? Pingora supports this but it is a little more involved configuration wise.

bestgopher commented 3 months ago

I need to route to Upstreams based on part of the URL

I have look into the documentation and the closes that I saw was to use modify_filter ( https://github.com/cloudflare/pingora/blob/main/docs/user_guide/modify_filter.md ) to route, but I will lose all healthcheck and round robin functionality since my upstreams are different services so one being up doesn't mean I can serve the request of other service

To be clear is the ask if you can proxy requests to different LoadBalancer clusters based on the downstream request URL? Pingora supports this but it is a little more involved configuration wise.

Could you provide some examples?

andrewhavck commented 3 months ago

Here's a simple example, will update our docs for future reference.

https://gist.github.com/andrewhavck/3dc29b96cf8272885db8cc3880bed6be

bestgopher commented 3 months ago

Here's a simple example, will update our docs for future reference.

https://gist.github.com/andrewhavck/3dc29b96cf8272885db8cc3880bed6be

thanks

kEpEx commented 3 months ago

Thanks for the example