Hi,
What is the difference between this new ngx-grpc-client-module and the
current ngx_http_grpc_module? Can't I use the current
ngx_http_grpc_module with some minor changes to achieve a similar effect?
On 7/7/22 16:08, Zexuan Luo wrote:
1. Background
1.1 Problem to be solved
More and more cloud-native applications are adopting gRPC as their API
standard, such as etcd, Dapr, and Envoy. In some cases, only the gRPC
API is available. Apache APISIX currently does not support access to
the API exposed by the gRPC service, and can only go through the HTTP
interface or develop a separate service to act as a proxy.
1.2 The benefits of solving this problem
1. Allow user to connect with their own gRPC services.
2. Embrace the ecosystem of Envoy and Dapr
3. Show our leadership of the popular technology and provide
something the rival is missing.
2. How to solve the problem
We will create a new Nginx module called ngx-grpc-client-module so
that we can interact with Nginx's event system. We choose to use a
mature gRPC implementation and write Lua/C binding for it.
Hence we study multiple gRPC clients:
Language: C++
Repo: https://github.com/grpc/grpc
Pro: 1. High performance
2. Widely used
Con: 1. Require nearly 2GB dependencies
2. Not easy to compile unless you are a C++ developer
Language: Go
Repo: https://github.com/grpc/grpc-go
Pro: 1. Written in pure Go
2. Widely used
3. Familiar to me
Con: 1. Low performance (We also study connect-go, but it has
worse performance)
Language: Rust
Repo: https://github.com/hyperium/tonic
Pro: 1. Written in pure Rust
2. High performance
Con: 1. Not familiar to me so I can't make sure it is mature enough
If APISIX is a company-inside project, I will choose to use C++.
However, APISIX is an open source project, and it is important to
lower the threshold for participation. People used to complain it is
hard to build APISIX from source, so we can't choose C++.
We can use Go first and switch to Rust in the future if the
performance is critical.
Changing the underneath gRPC implementation won't break the Lua API
provided by this module.
The process of unary request can be done in the steps below:
1. Encode the proto message and start gRPC call
2. Create task ctx, call the Go code and suspend Lua thread
3. Execute gRPC code, put the task ctx and final result to the task done queue
4. Wait on the task done queue
5. Remove the data from task done queue
6. Add the task ctx to Nginx's posted event queue and re-wait on the
task done queue
7. Resume Lua thread
8. Finish the gRPC call and decode proto message
Step 1/8 are done in the Lua.
Step 2/4/6/7 are done in the C code.
Step 3/5 are done in the Go (or other gRPC implementation)
Client / Server stream requests can be considered as one initial call
plus several unary read/write operations.