Skip to main contentThe architecture of fRPC is based on the standard Server/Client model that a lot of other RPC frameworks are follow.
The idea is that the Client makes a connection with the Server, and then sends a structured
request. Based on the request type, the Server runs a handler that then returns a response or an error.
The Server then forwards that response object (or the error) back to the Client.
From the perspective of the Client, they have simply called a function and received a response. The fact
that the request is serialized and transmitted to the Server is hidden for simplicity.
To dig into how the underlying architecture of both the Server and Client work, it is first
important to understand that the underlying Frisbee protocol does not have any notion of a request
or response. When Frisbee sends a Packet of data, it does not wait for a response. This makes
the protocol suitable for a number of use cases (like real-time streaming), but also means that Request/Reply semantics
need to be implemented in the application logic - in this case, the code that fRPC generates.
Server Architecture
The generated fRPC Server is based on the RPC Services that are defined in the proto3
file that is passed to the protoc compiler. Developers are responsible for implementing the generated
Service interfaces and passing that into the Server constructor.
The Server then takes that implementation and creates a handler table that maps the request type to the
accompanying function in the provided Service implementation.
When it receives a request, it looks up the request type in the handler table and calls the accompanying
function with the deserialized Request object. The function then returns a Response object that
is serialized and sent back to the Client.
Client Architecture
The generated fRPC Client is also based on the RPC Services that are defined in the
proto3 file that is passed to the protoc compiler. Based on the RPC Calls defined in those services,
fRPC generates a number of Client helper functions - one for each possible RPC Call.
As mentioned before, Frisbee does not have any notion of a request or response - this means that we must implement
the ability to wait for a response from the Server in the application logic. We need to also be able to map
those incoming responses to the correct ongoing request.
To achieve this, fRPC Clients make use of an in-flight requests table that maps a request ID to a channel
that can be listened to for a response. When an RPC function is called, it generates a request ID, serializes the request
object and sends it to the Server. When a response object is received from the Server, it is
deserialized and request ID is looked up in the in-flight requests table.
The response is then pushed into the channel associated with the request ID, where it is read by the RPC function
that made the request in the first place. This response unblocks the RPC caller and the response object (or an error)
is returned.