Hi all, I am wondering if anyone has had some experience writing a GRPC client and/or server using the ProtoBuf.jl and HTTP.jl packages (both of which appear to be in good working order for 1.0). I found an old GRPC.jl package, but it relies on HTTP2.jl which doesn’t appear to have been updated in some time.
Protobuf.jl has an example of writing an RPC client and server (using tcp sockets) (https://github.com/JuliaIO/ProtoBuf.jl/blob/master/test/services/testsvc.jl), so I’d like to model what I’m doing off of that (except using HTTP requests instead). The problem is I can’t quite figure out how to get the functionality of creating an HTTP connection session object that I can interact with in HTTP.jl. For example, this is some of the older code in the GRPC.jl library (again relying on HTTP2.jl):
Well, that’s kind of a fundamental difference between the http 1.x & http 2.0 protocols (i.e. native support for persistent sessions), so no, there’s not really a way to replicate that functionality w/ plain http. Now, you’d probably have better success by replacing the http2 parts w/ WebSockets.jl. websockets use a similar persistent connection to send messages back & forth; I don’t think it’d be too hard to adapt the code to work for this case, but I’m also far from an expert on websockets.
I just found your post while searching for HTTP2.
Both HTTP/1.1 and HTTP/2 support persistent bi-directional io (without WebSockets).
I believe the key difference between HTTP/1.1 and HTTP/2 is that the latter adds support for interleaving frames from multiple sessions on a single connection. What I have read about HTTP/2 suggests that while it implements compression and connection sharing and binary framing under the hood, it does not introduce any semantic user visible changes to HTTP/1.1.
If you need multiple simultaneous sessions with HTTP/1.1 you’ll need to open multiple connections. With HTTP/2 your code will look exactly the same, but your HTTP/2 library might quietly reuse an existing connection when it can.
WebSockets is useful if you’re communicating with a web browser, because web browsers have a user friendly javascript API for that protocol. However, HTTP/1.1 has bi-directional message framing built in so if you’re in control of the server and the client there is no need for WebSockets.
Here is a simple example of a bi-directional chat app using HTTP.jl:
using HTTP
function chat(io::HTTP.Stream)
@async while !eof(io)
write(stdout, readavailable(io), "\n")
end
while isopen(io)
write(io, readline(stdin))
end
end
chat_server() = HTTP.listen("127.0.0.1", 8087) do io::HTTP.Stream
startwrite(io)
chat(io)
end
chat_client() = HTTP.open("POST", "http://127.0.0.1:8087", #= verbose=3 =#) do io::HTTP.Stream
startread(io)
chat(io)
end
If you turn the verbose=3 client option on you can see how the framing works…
Also, could someone fill me in on why the HTTP.jl package is important here? As I would have imagined that RPC would bypass HTTP and use TCP connections directly. What am I missing?
I have not looked at the source, but HTTP could be used with grpc-web. However, the native gRPC protocol should be preferred when not restricted to http like browsers.