The gRPC API for sending and receiving is based upon messages. However, messages cannot be transmitted directly over a network; they must first be converted into bytes. This document describes how gRPC-Go converts messages into bytes and vice-versa for the purposes of network transmission.
A Codec
contains code to serialize a message into a byte slice (Marshal
) and
deserialize a byte slice back into a message (Unmarshal
). Codec
s are
registered by name into a global registry maintained in the encoding
package.
A typical Codec
will be implemented in its own package with an init
function
that registers itself, and is imported anonymously. For example:
package proto
import "google.golang.org/grpc/encoding"
func init() {
encoding.RegisterCodec(protoCodec{})
}
// ... implementation of protoCodec ...
For an example, gRPC's implementation of the proto
codec can be found in
encoding/proto
.
By default, gRPC registers and uses the "proto" codec, so it is not necessary to
do this in your own code to send and receive proto messages. To use another
Codec
from a client or server:
package myclient
import _ "path/to/another/codec"
Codec
s, by definition, must be symmetric, so the same desired Codec
should
be registered in both client and server binaries.
On the client-side, to specify a Codec
to use for message transmission, the
CallOption
CallContentSubtype
should be used as follows:
response, err := myclient.MyCall(ctx, request, grpc.CallContentSubtype("mycodec"))
As a reminder, all CallOption
s may be converted into DialOption
s that become
the default for all RPCs sent through a client using grpc.WithDefaultCallOptions
:
myclient := grpc.Dial(ctx, target, grpc.WithDefaultCallOptions(grpc.CallContentSubtype("mycodec")))
When specified in either of these ways, messages will be encoded using this
codec and sent along with headers indicating the codec (content-type
set to
application/grpc+<codec name>
).
On the server-side, using a Codec
is as simple as registering it into the
global registry (i.e. import
ing it). If a message is encoded with the content
sub-type supported by a registered Codec
, it will be used automatically for
decoding the request and encoding the response. Otherwise, for
backward-compatibility reasons, gRPC will attempt to use the "proto" codec. In
an upcoming change (tracked in this
issue), such requests will be
rejected with status code Unimplemented
instead.
Sometimes, the resulting serialization of a message is not space-efficient, and it may be beneficial to compress this byte stream before transmitting it over the network. To facilitate this operation, gRPC supports a mechanism for performing compression and decompression.
A Compressor
contains code to compress and decompress by wrapping io.Writer
s
and io.Reader
s, respectively. (The form of Compress
and Decompress
were
chosen to most closely match Go's standard package
implementations of compressors). Like
Codec
s, Compressor
s are registered by name into a global registry maintained
in the encoding
package.
A typical Compressor
will be implemented in its own package with an init
function that registers itself, and is imported anonymously. For example:
package gzip
import "google.golang.org/grpc/encoding"
func init() {
encoding.RegisterCompressor(compressor{})
}
// ... implementation of compressor ...
An implementation of a gzip
compressor can be found in
encoding/gzip
.
By default, gRPC does not register or use any compressors. To use a
Compressor
from a client or server:
package myclient
import _ "google.golang.org/grpc/encoding/gzip"
Compressor
s, by definition, must be symmetric, so the same desired
Compressor
should be registered in both client and server binaries.
On the client-side, to specify a Compressor
to use for message transmission,
the CallOption
UseCompressor
should be used as follows:
response, err := myclient.MyCall(ctx, request, grpc.UseCompressor("gzip"))
As a reminder, all CallOption
s may be converted into DialOption
s that become
the default for all RPCs sent through a client using grpc.WithDefaultCallOptions
:
myclient := grpc.Dial(ctx, target, grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip")))
When specified in either of these ways, messages will be compressed using this
compressor and sent along with headers indicating the compressor
(content-coding
set to <compressor name>
).
On the server-side, using a Compressor
is as simple as registering it into the
global registry (i.e. import
ing it). If a message is compressed with the
content coding supported by a registered Compressor
, it will be used
automatically for decompressing the request and compressing the response.
Otherwise, the request will be rejected with status code Unimplemented
.