Closed koonpeng closed 4 years ago
No more dependency on soss (soss is not actively developed and is a low priority component of rmf).
Does this mean we will write something entirely new in the server to replace soss entirely or will it be more like a layer to hide the bridge but the bridge is still needed somewhere?
My current understanding is that no dependency on soss === soss does not connect directly to the dashboard but to the canonical server instead.
sry, I meant for it to connect to ros2 directly, bypassing soss. It can use either rclnodejs, rclpy or rclcpp, or other rcl bindings depending what language we use for the server. I will update the pictures.
+1 to this idea. Outdated after update of the issue description. Thinking a little further in time, we could have a possible bottleneck with the proposed architecture; maybe we can solve that on deploy time, like for example, having one deployed server per service or having a load balancer.
Does this mean we will write something entirely new in the server to replace soss entirely or will it be more like a layer to hide the bridge but the bridge is still needed somewhere?
My current understanding is that no dependency on soss === soss does not connect directly to the dashboard but to the canonical server instead.
Lol, the same thing cross my mind.
sry, I meant for it to connect to ros2 directly, bypassing soss. It can use either rclnodejs, rclpy or rclcpp, or other rcl bindings depending what language we use for the server. I will update the pictures.
Cool, thanks for the clarification.
The new proposal will unify all data sources into a canonical system (graphql for example). The server will convert the various data sources into a format suitable to be consumed by the dashboard.
Not against Graphql, and just to be on the same page, we will be just using the Schema Stitching for Combining Schemas
benefit of it (maybe the no API versioning too). I'm saying this (and maybe I'm wrong) because I'm not seeing a case where we will have an overfetching or an underfetching because what we want to get are the messages that already have all the information in a request.
We can use apollo as our Graphql client. https://www.apollographql.com/docs/react/. It has a lot of cool functionalities:
src: "https://www.apollographql.com/docs/react/"
We can use all of this cool features except for the Local State
(happily =) )
HTH,
updated the opening comment with a comparison of some rpc frameworks, at the moment it doesn't look like there is anything suitable, what does everyone think?
At the moment, I feel that the best approach now seems to be either writing a js client for msgpack-rpc, or using a custom variant of json-rpc that uses msgpack/bson as the payload.
At the moment, I feel that the best approach now seems to be either writing a js client for msgpack-rpc, or using a custom variant of json-rpc that uses msgpack/bson as the payload.
Yeah, you're right it doesn't look like there is anything suitable for our needs. I found a client for messagepack-rpc (I think it can be useful if we want to go through that path). https://stackoverflow.com/questions/9457657/how-to-invoke-a-messagepack-rpc-service-from-javascript https://github.com/nori0428/msgpack.rpc.js
Since this doesn't have native browser support we may want to check the performance of this under heavy load circumstances.
custom variant of json-rpc that uses msgpack/bson as the payload.
I don't have anything against this either, but wouldn't we have to double convert messages to use the content in this case?
Also, I think we can use the API-gateway architecture to have one point to access multiple services. https://www.redhat.com/en/topics/api/what-does-an-api-gateway-do#:~:text=An%20API%20gateway%20is%20an,and%20return%20the%20appropriate%20result.
I'll keep digging in case I find something else.
Also, I think we can use the API-gateway architecture to have one point to access multiple services. https://www.redhat.com/en/topics/api/what-does-an-api-gateway-do#:~:text=An%20API%20gateway%20is%20an,and%20return%20the%20appropriate%20result.
You are right, what we are looking for is more of an api gateway instead of just a simple rpc mechanism. These are some of the offerings available (https://alternativeto.net/browse/search?q=api-gateway). One of our main data sources is ros2, I doubt that is supported by any of the popular offerings, but they should all support plugins to add custom backends. I wonder if we should use one of these gateways or make something much less complex ourselves?
Edit: looks like there really isnt any good way to add a ros2 plugin, the most promising is Tyk but I have my doubts.
You are right, what we are looking for is more of an api gateway instead of just a simple rpc mechanism. These are some of the offerings available (https://alternativeto.net/browse/search?q=api-gateway). One of our main data sources is ros2, I doubt that is supported by any of the popular offerings, but they should all support plugins to add custom backends. I wonder if we should use one of these gateways or make something much less complex ourselves?
Edit: looks like there really isnt any good way to add a ros2 plugin, the most promising is Tyk but I have my doubts.
- krakend: plugin must be in go, there is no stable rcl bindings for go
- kong: go or lua, neither of which has rcl bindings
- tyk: python, javascript, lua, .net, java. python has 1st class ros2 support, js, java, .net has third-party support. However the python example uses synchronous programming, and the doc says the python interpreter is embedded in Tyk so I'm not sure if we can run rclpy on it.
Cool! thanks for the summary! Yeah, you're right, if we can't run rclpy we'll run out of options, as you said, maybe we should start to handle the possibility of doing something less complex ourselves.
Hi @matiasinsaurralde, just in case you can give us a hand,
We need to use an API gateway and we're considering Tyk because it looks great. The examples we saw use synchronous programming, and the doc says that the Python interpreter is embedded in Tyk. What is holding us back (@koonpeng just correct me if I'm wrong) is that we have to install a library called rclpy (ROS Client Library for Python) and use asynchronous programming.
So my question is this, would there be some simple way to add that library to the embedded python interpreter and use that library in a plugin? Could asynchronous programming be used?
Hi, the way we embed Python into Tyk is by loading the CPython on runtime, using libdl
/dlopen
, this would make use of your default Python installation. You should be able to use any Python module with it as long as you've previously installed it using pip
or similar.
I haven't tried async Python code in this context and I'm not sure if CPython has any limitations in that scenario, I would say that we embed it in a quite standard way.
I would be happy to try it out, if you can provide a simple rclpy
sample that I could run.
Hi, the way we embed Python into Tyk is by loading the CPython on runtime, using
libdl
/dlopen
, this would make use of your default Python installation. You should be able to use any Python module with it as long as you've previously installed it usingpip
or similar. I haven't tried async Python code in this context and I'm not sure if CPython has any limitations in that scenario, I would say that we embed it in a quite standard way.
Awesome! I really appreciate your help tocayo! =)
I would be happy to try it out, if you can provide a simple
rclpy
sample that I could run.
I'll check with @koonpeng if it has something at hand.
Hi @matiasinsaurralde, thanks for taking the time to look at this.
For abit of background, we are currently receiving data from multiple sources, they are mainly websockets and ros2 now but there is a possibility in the future that we will need to receive data from other obscure protocols like hl7. These non-web protocols would need a bridge, the current idea is to convert them to msgpack and serve it as binary through http (preferably http2) or websockets.
We are looking at Tyk to help us manage all these endpoints, the challenge would be to get these non-web protocols to work, with regards to ros2 the considerations we have are:
For reference, here is an example rclpy code to perform a ros2 subscription
rclpy.spin
starts its own event loop and a callback is invoked when a message comes in. So the Tyk plugin cannot return a response synchronously, and would also need to "stream" the response in chunks as the messages arrive.
Replaces the numerous clients (soss, trajectory, negotiation, others) with a canonical server, which handles marshaling between each data sources.
Current:
New:
Current problem: Because the dashboard connects directly to each service, they must support web standards (http, websockets etc). ROS2 is an example protocol which does not support web standards, so we have to use soss to bridge it. There may be other protocols which may not support web standards which we may need in the future, hl7 for example. With the current pattern, we would need a bridge for each of these unsupported protocols, and each bridge would also brings in another client to implement in the dashboard.
The new proposal will unify all data sources into a canonical system (graphql for example). The server will convert the various data sources into a format suitable to be consumed by the dashboard.
Advantages:
Disadvantages:
I looked at some RPC libraries available, here are some comparisons on the feature set that we would need.
See https://docs.google.com/spreadsheets/d/1IPN_rKSwGaXleJ3KcT6TCHM1V1uuOye76gk3mJxREqs/edit?usp=sharing for more detailed notes.
Some rpc implementations have a type system (graphql, grpc etc). This usually means a language agnostic message definition files, this could be a double edged sword, the advantage of it is that it allows the framework to generate language specific constructs to provide strongly typed bindings. The disadvantage is that as long as we are only supporting js/ts, we can just write those definitions directly. It also brings in another layer of complexity as ros2 already has its own type system which
romi-js
uses to generate typescript definitions, moving to these rpc frameworks would mean converting ros2's definitions to the rpc's format and then generating typescript code based on that.