Coder Social home page Coder Social logo

networknt / light-router Goto Github PK

View Code? Open in Web Editor NEW
5.0 20.0 3.0 514 KB

A client side service mesh router designed for legacy system that cannot leverage client module

License: Apache License 2.0

Shell 3.08% Java 95.80% Dockerfile 1.12%
service-discovery service-mesh data-plane light-4j proxy router servicediscovery

light-router's Introduction

light-router

Deprecated: It is replaced by the light-gateway with light-router and light-proxy features.

A client-side service mesh router designed for the legacy system that cannot leverage the light-4j client module

Stack Overflow | Google Group | Gitter Chat | Subreddit | Youtube Channel | Documentation | Contribution Guide |

Framework usage workflow diagram

workflow

Light-router provides the Router Assisted Service Discovery

Light-router is a service that provides consumers with another option to make service discovery if they cannot leverage the client module provided by light-4j.

Light-router is primarily used for service discovery and technically there is client-side discovery only as it is called “service discovery” and only clients need to do that. All discovery can just exist on client-side.

The difference is that the discovery code in client or on the client host or on another static server in a data center. An additional scenario is to use light-router as BFF for SPA or Mobile.

To learn how to use light-router, pleases refer to

Sample on local environment

Start a sample API from light-example-4j:

 cd ~/networknt
 git clone [email protected]:networknt/light-example-4j.git
 cd ~/networknt/light-example-4j/servicemesher/services

 mvn clean install -Prelease

cd petstore-service-api

java -jar target/petstore-service-api-3.0.1.jar

The petstore light-api will start on local https 8443 port.

verify by access the service directly on https://localhost:8443/

curl --location --request GET 'https://localhost:8443/v1/pets' \
--header 'Content-Type: application/json' \
--data-raw ''

Now start light-router and try to access the petstore light-api through light-router:

 cd ~/networknt
 git clone [email protected]:networknt/light-router.git

 mvn clean install
 java -jar -Dlight-4j-config-dir=config/local  target/light-router.jar

Verify through router handler by adding service_id in the header

curl --location --request POST 'https://localhost:9443/v1/pets' \
--header 'Content-Type: application/json' \
--header 'service_id: com.networknt.petstore-1.0.0' \
--data-raw '{"id":111, "name": "cat"}'

Verify through serviceDict handler and router handler by path mapping:


curl --location --request GET 'https://localhost:9443/v1/pets' \
--header 'Content-Type: application/json' \
--data-raw '{"accountId":1,"transactioType":"DEPOSIT","amount":20}'

light-router's People

Contributors

balloonwen avatar ddobrin avatar dependabot[bot] avatar dguncb avatar dz-1 avatar gavinchenyan avatar jsu216 avatar logi avatar nicholasazar avatar pre-commit-ci[bot] avatar sreeni1990 avatar stevehu avatar wswjwjccjlu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

light-router's Issues

Host header setting incorrect for outbound HTTP calls

The Host header for the outbound HTTP connection is being set with the inbound host name. This prevents usage of downstream applications that use the Host header for routing such as Azure web apps.
Need to set the Host header using the outgoing host name and port from RouterProxyClient on the first connection (ConnectNotifier) and for subsequent calls using a cached open connection.

Error handling in router interface & with service discoery

Response proper messages in error scenarios including:
Service discovery:
service id is missing in header
service id is provided but not configured (direct)
service is not found in consul
Security (SAML + JWT):
SAML or JWT is missing

create a JwtVerifyHandler based on handler.yml

As we know, we have JwtVerifyHandlers in each individual frameworks and they are responsible for verifying the JWT token in the request header to authorize the request. As the security requirement is defined in the specifications and each framework has its own spec format, that is why we have several implementations.

When light-router is used to secure backend services, it is very hard to create a combined specification for the router instance especially when backend services are implemented in different frameworks. Given there are a lot of extra works to bring the spec to the router instance, we have to find a simpler way to enforce security on the light-router instance.

With the handler module introduced recently to support multiple chains in the same instance and all the endpoints are defined in the handler.yml config file. We can enhance the handler module to put the JWT token scope in the path/method definition in the handler.yml and pass the info to the subsequent JwtVerifyHandler to verify it. This enables security at light-router without specification and makes the light-router more flexible in terms of usage.

What do you think?

Support bypassing service discovery & load balance

This issue is created for Jira ticket API-36.
It allows the client of the light-router to specify the service url where the requests should be forwarded to.
Another issue, #362 in light-4j is created to supported the service url header constant.

add deref handle to the dependencies but not in the middleware

For some customers who want to send by-reference token to the Internet but use JWT internal, this handler can deref the opaque token to JWT token on the router in order to call internal APIs. As this is only an optional handler, it is just included into the dependencies but not wire into the middleware handler chain.

implement canary deployments

The idea behind canary deployment (or rollout) is to introduce a new version of a service by first testing it using a small percentage of user traffic, and then if all goes well, increase, possibly gradually in increments, the percentage while simultaneously phasing out the old version. If anything goes wrong along the way, we abort and rollback to the previous version. In its simplest form, the traffic sent to the canary version is a randomly selected percentage of requests, but in more sophisticated schemes it can be based on the region, user, or other properties of the request.

For more info, please refer to https://istio.io/blog/2017/0.1-canary/

upgrade light-router to use handler.yml instead of PathProvider

We need to serve the static content from the router instance and it would be easier to use handler.yml instead of PathProvider. The other benefit of hanlder.yml is the validate the path and method before routing the request to the downstream service. What do you think?

Router loses parts of lare request bodies.

I have a service which accepts POSTed JSON payloads which are parsed by BodyHandler. It has been stress tested with multiple concurrent processes which repeatedly upload the same payloads ranging in in size from 2.8K to 109K of test data and it is reliable after tens of thousands of iterations.

Adding a light-router (port 8080) in front of this, even with only a single instance of the service (port 2400) again works reliably for the smaller payloads of 2.8K. Slowly increasing the payload size and running the tight upload loop, we start getting 503 responses when we cross the 32K boundary.

Running the service in the IDEA debugger with a router in front of it we see that the BodyHandler fails to parse the payload and copying the string to a file and comparing with the original payload, we see that there is a chunk of just over 16K missing from the string being parsed compared to the payload that was sent.

Looking at the router code my initial suspicion is that the connection caching in RouterProxyClient is not thread safe and bad things start happening when the payload size exceeds the size of a buffer somewhere.

Some observations:

  • The limits are a tad over 32K and the missing data is just over 16K in utf-8 encoded files with some amount of non-ascii text, so these problems might be happening on some text-buffer level rather than a byte-buffer level to get nice round powers of 2.
  • The larger the payloads are, then more likely they are to fail.
  • Adding a 1 second sleep between calls does not make the problem go away.

Making a stand-alone test case for this will be a bit tricky so I'm opening the issue without one before the week-end while it's fresh in my mind.

Add new handler to support SAML grant type flow

Support must be added to support the new SAML grant type OAuth flow.

A new handler, SAMLGrantHandler, will be added to support this OAuth flow.

Light Router must accept a JWT and a SAML token in it's header under the header keys assertion (for SAML) and client_assertion (for JWT).

It must then POST these tokens* to an OAuth authorization server (encoded as x-www-for-urlencoded) and receive a JWT in response, and then set this new Bearer {JWT} in its header under the Authorization key before service lookup and forwarding the request.

    • In addition to the two tokens, the authorization server expects the following additional values in x-www-form-urlencoded payload:
  • grant_type: urn:ietf:params:oauth:grant-type:saml2-bearer
  • scope: {blank separated list of OAuth scopes}*
  • client_assertion_type: urn:ietf:params:oauth:client-assertion-type:jwt-bearer

* Note that the scope key/value pair is optional.

update Dockerfile-Debug to allow all addresses to bind

When connecting to the debug docker container other than running locally, we might encounter a connection problem. By setting the address=*:5005, we allow the application running within the docker binding to any address. As long as the docker network is host, we can connect remotely.

update router to support HTTP/1.1 as an option

Currently, the incoming traffic can be HTTP/2 or HTTP/1.1 configurable but the outgoing traffic is hard-coded to HTTP/2 only. So far, we are OK as all of our downstream services are built on top of light-4j which support HTTP2 natively. When using the light-router with other downstream services, we need to provide an option to support HTTP/1.1 in the configuration.

enhance PathPrefixServiceHandler to support both path and method

In order to allow light-router to discover services, the serviceId must be in the header of the client request. This is a little intrusive to the client so I have built the PathServiceHandler to allow mapping from the requesting endpoint to a serviceId and put into the request header automatically. It depends on the endpoint in the auditInfo attachment populated by the openapi-meta or swagger-meta from light-rest-4j.

There are two drawbacks.

  • It assumes that the backend service is REST only.
  • The backend service openapi.yaml/json or swagger.json must be deployed to the light-router instance. It might be OK if there is only one service behind the light-router but most of the cases, there are multiple services behind the light-router.

Given the inconvenience, @logi created PathPrefixServiceHandler which can determine the serviceId from the path prefix. This works in his use case very well and I am using it for some of our services. However, there is room to improve it after we have support handler.yml with multi-chains. The current implementation only considers the path prefix and cannot handler the following scenarios.

  • If you have two services share the same prefix. For example, in CQRS, the read service and write service might have the same path but get and post methods.
  • For some of the services that cannot be differentiated by just the prefix. We need to further parse into the path parameters.

Since we are parsing the path and method in the handler module, we can use the result to map to serviceId in this middleware handler. This gives us more flexibility and hides the logic from the original client. My suggestion is to create a new middleware handler and deprecate PathServiceHandler and PathPrefixServiceHandler but keep them for a while in case someone is using it. What do you think?

add pathServiceHandler to map endpoints to serviceId

Normally, the client need to pass service_id and env_tag headers to the light-router in order to allow light-router to do the service discovery. However, if the downstream APIs have distinct endpoints and no common services like /health or /server/info are called. We can use this handler to derive the serviceId from the endpoint. The HeaderHandler can be used to set the env_tag as well so that client can just send the normal request based on the downstream APIs specification. If this is used, we need to have openapi.json specification on the router.

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.