Go Orb is a framework for distributed systems development, it can be seen as the successor of go-micro.dev/v4.
The core of go-orb has been completely refactored, to support the removal of reflect and introduction of wire.
Go Orb is in BETA status, backward incompatible changes will only be introduced with minor (v0.4.0) releases.
Please try out go-orb, report any issues you find and spread the word.
Go Orb provides the core requirements for distributed systems development including RPC and Event driven communication. The Go Orb philosophy is sane defaults with a pluggable architecture. We provide defaults to get you started quickly but everything can be easily swapped out.
Go Orb abstracts away the details of distributed systems. Here are the main features.
-
Config - Load dynamic config from anywhere. The config interface provides a way to load application level config from any source such as env vars, file and http. You can merge the sources and even define fallbacks.
-
Service Discovery - Automatic service registration and name resolution. Service discovery is at the core of Go Orb service development. When service A needs to speak to service B it needs the location of that service. The default discovery mechanism is multicast DNS (mdns), a zeroconf system.
-
Message Encoding - Dynamic message encoding based on content-type. The client and server will use codecs along with content-type to seamlessly encode and decode Go types for you. Any variety of messages could be encoded and sent from different clients. The client and server handle this by default. This includes protobuf and json by default.
-
RPC Client/Server - RPC based request/response with support for bidirectional streaming. We provide an abstraction for synchronous communication. A request made to a service will be automatically resolved, load balanced, dialled and streamed.
-
RPC over event topics - RPC over event topics, makes RPC even easier.
-
Pluggable Interfaces - Go Orb makes use of Go interfaces for each distributed system abstraction. Because of this these interfaces are pluggable and allows Go Orb to be runtime agnostic. You can plugin any underlying technology.
-
Strongly tested and linted - We use golangci-lint to ensure code quality and we have a comprehensive test suite, all lints and tests are run on CI.
Please see the examples repo.
Use of wire
With wire we gain:
- compile-time safety
- no more globals
It was the main reason for starting orb, wire allows us to decouple the components and plugins.
we have been working hard on removing all usage of reflect.
Orb allows you to listen on multiple port's with different protocols: gRPC, HTTP, HTTPS, DRPC, HTTP2, H2C, HTTP3. See the config system entry on howto configure it.
Advanced config system
With orb you can configure your plugins with a config file or environment options.
service1:
server:
handlers:
- UserInfo
middlewares:
- middleware-1
entrypoints:
grpc:
plugin: grpc
insecure: true
reflection: false
client:
middlewares:
- name: log
- name: retry
registry:
enabled: true
plugin: mdns
timeout: 350
domain: svc.orb
service1:
server:
handlers:
- UserInfo
middlewares:
- middleware-1
- middleware-2
entrypoints:
hertzhttp:
plugin: hertz
http2: false
insecure: true
grpc:
plugin: grpc
insecure: true
reflection: false
http:
plugin: http
insecure: true
drpc:
plugin: drpc
client:
middlewares:
- name: log
- name: retry
registry:
plugin: consul
address: consul:8500
These 2 config's with different options will both work, we first parse the config, get the "plugin" from it and pass a map[any]any
with all config data to the plugin.
Both work with a single binary. :)
Return types as a result instead of HTTP req format.
New:
req := HelloRequest{Name: "test"}
// Look at resp, it's now returned as a result.
resp , err := client.Request[HelloResponse](context.Background(), clientDi, "org.orb.svc.hello", "Say.Hello", &req)
Old:
req := c.c.NewRequest(c.serviceName, "Greeter.Hello", in)
out := new(HelloResponse)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
go-orb has support for sending nearly anything you throw in as application/json
to the Server.
resp , err := client.Request[map[string]any](context.Background(), clientDi, "org.orb.svc.hello", "Say.Hello", `{"name": "Alex"}`, client.WithContentType(codecs.MimeJSON))
req := make(map[string]any)
req["name"] = "Alex"
resp , err := client.Request[map[string]any](context.Background(), clientDi, "org.orb.svc.hello", "Say.Hello", req, client.WithContentType(codecs.MimeJSON))
We like structured logging, this is why we replaced all logging with one based on slog.
We made sure that go-orb/go-orb (the core) is just a bunch of interfaces as well as some glue code, the most real code lives in go-orb/plugins.
Everything is linted and staticaly analyzed by golangci-lint, enforced with CI pipelines on github.
Chat with us on Discord or Matrix.
We use version v1.64.5 of golangci-lint.
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.64.5
golangci-lint run --config .golangci.yaml
To prevent import cycles it's not allowed to import go-orb/plugins here.
We do not accept commits that fail to lint, use ./scripts/test.sh lint all
.
A lot of this is copy&pasted from go-micro, top contributors have been:
- Asim Aslam the founder/creator of go-micro.
- Milos Gajdos
- ben-toogood
- Vasiliy Tolstov
- Johnson C
go-orb is Apache 2.0 licensed and is based on go-micro.