mirror of
https://github.com/go-micro/go-micro.git
synced 2025-09-16 08:36:30 +02:00
@@ -1,28 +0,0 @@
|
||||
# gRPC Service
|
||||
|
||||
A simplified experience for building gRPC services.
|
||||
|
||||
## Overview
|
||||
|
||||
The **gRPC service** makes use of [go-micro](https://github.com/micro/go-micro) plugins to create a simpler framework for gRPC development.
|
||||
It interoperates with standard gRPC services seamlessly, including the [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway).
|
||||
The grpc service uses the go-micro broker, client and server plugins which make use of
|
||||
[github.com/grpc/grpc-go](https://github.com/grpc/grpc-go) internally.
|
||||
This means we ignore the go-micro codec and transport but provide a native grpc experience.
|
||||
|
||||
<img src="https://micro.mu/docs/images/go-grpc.svg" />
|
||||
|
||||
## Features
|
||||
|
||||
- **Service Discovery** - We make use of go-micro's registry and selector interfaces to provide pluggable discovery
|
||||
and client side load balancing. There's no need to dial connections, we'll do everything beneath the covers for you.
|
||||
|
||||
- **PubSub Messaging** - Where gRPC only provides you synchronous communication, the **gRPC service** uses the go-micro broker
|
||||
to provide asynchronous messaging while using the gRPC protocol.
|
||||
|
||||
- **Micro Ecosystem** - Make use of the existing micro ecosystem of tooling including our api gateway, web dashboard,
|
||||
command line interface and much more. We're enhancing gRPC with a simplified experience using micro.
|
||||
|
||||
## I18n
|
||||
|
||||
### [中文](README_cn.md)
|
@@ -1,25 +0,0 @@
|
||||
# Micro gRPC [](https://opensource.org/licenses/Apache-2.0) [](https://godoc.org/github.com/micro/go-micro/service/grpc) [](https://travis-ci.org/micro/go-micro/service/grpc) [](https://goreportcard.com/report/github.com/micro/go-micro/service/grpc)
|
||||
|
||||
Micro gRPC是micro的gRPC框架插件,简化开发基于gRPC的服务。
|
||||
|
||||
## 概览
|
||||
|
||||
micro提供有基于Go的gRPC插件[go-micro](https://github.com/micro/go-micro),该插件可以在内部集成gPRC,并与之无缝交互,让开发gRPC更简单,并支持[grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway)。
|
||||
|
||||
micro有面向gRPC的[客户端](https://github.com/micro/go-plugins/tree/master/client)和[服务端](https://github.com/micro/go-plugins/tree/master/server)插件,go-grpc库调用客户端/服务端插件生成micro需要的gRPC代码,而客户端/服务端插件都是从[github.com/grpc/grpc-go](https://github.com/grpc/grpc-go)扩展而来,也即是说,我们不需要去知道go-micro是如何编解码或传输就可以使用原生的gRPC。
|
||||
|
||||
## 特性
|
||||
|
||||
- **服务发现** - go-micro的服务发现基于其[注册](https://github.com/micro/go-plugins/tree/master/registry)与[选择器](https://github.com/micro/go-micro/tree/master/selector)接口,实现了可插拔的服务发现与客户端侧的负载均衡,不需要拨号连接,micro已经把所有都封装好,大家只管用。
|
||||
|
||||
- **消息发布订阅** - 因为gRPC只提供同步通信机制,而**Go gRPC**使用go-micro的[broker代理](https://github.com/micro/go-micro/tree/master/broker)提供异步消息,broker也是基于gRPC协议。
|
||||
|
||||
- **Micro生态系统** - Micro生态系统包含工具链中,比如api网关、web管理控制台、CLI命令行接口等等。我们通过使用micro来增强gRPC框架的易用性。
|
||||
|
||||
## 示例
|
||||
|
||||
示例请查看[examples/greeter](https://github.com/micro/go-micro/service/grpc/tree/master/examples/greeter)。
|
||||
|
||||
## 开始使用
|
||||
|
||||
我们提供相关文档[docs](https://micro.mu/docs/go-grpc_cn.html),以便上手。
|
@@ -1,58 +1,124 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro"
|
||||
broker "github.com/micro/go-micro/broker"
|
||||
client "github.com/micro/go-micro/client/grpc"
|
||||
server "github.com/micro/go-micro/server/grpc"
|
||||
"github.com/micro/go-micro/client"
|
||||
gclient "github.com/micro/go-micro/client/grpc"
|
||||
"github.com/micro/go-micro/server"
|
||||
gserver "github.com/micro/go-micro/server/grpc"
|
||||
"github.com/micro/go-micro/service"
|
||||
)
|
||||
|
||||
type grpcService struct {
|
||||
opts service.Options
|
||||
}
|
||||
|
||||
func newService(opts ...service.Option) service.Service {
|
||||
options := service.NewOptions(opts...)
|
||||
|
||||
return &grpcService{
|
||||
opts: options,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *grpcService) Name() string {
|
||||
return s.opts.Server.Options().Name
|
||||
}
|
||||
|
||||
// Init initialises options. Additionally it calls cmd.Init
|
||||
// which parses command line flags. cmd.Init is only called
|
||||
// on first Init.
|
||||
func (s *grpcService) Init(opts ...service.Option) {
|
||||
// process options
|
||||
for _, o := range opts {
|
||||
o(&s.opts)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *grpcService) Options() service.Options {
|
||||
return s.opts
|
||||
}
|
||||
|
||||
func (s *grpcService) Client() client.Client {
|
||||
return s.opts.Client
|
||||
}
|
||||
|
||||
func (s *grpcService) Server() server.Server {
|
||||
return s.opts.Server
|
||||
}
|
||||
|
||||
func (s *grpcService) String() string {
|
||||
return "grpc"
|
||||
}
|
||||
|
||||
func (s *grpcService) Start() error {
|
||||
for _, fn := range s.opts.BeforeStart {
|
||||
if err := fn(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.opts.Server.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, fn := range s.opts.AfterStart {
|
||||
if err := fn(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *grpcService) Stop() error {
|
||||
var gerr error
|
||||
|
||||
for _, fn := range s.opts.BeforeStop {
|
||||
if err := fn(); err != nil {
|
||||
gerr = err
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.opts.Server.Stop(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, fn := range s.opts.AfterStop {
|
||||
if err := fn(); err != nil {
|
||||
gerr = err
|
||||
}
|
||||
}
|
||||
|
||||
return gerr
|
||||
}
|
||||
|
||||
func (s *grpcService) Run() error {
|
||||
if err := s.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// wait on context cancel
|
||||
<-s.opts.Context.Done()
|
||||
|
||||
return s.Stop()
|
||||
}
|
||||
|
||||
// NewService returns a grpc service compatible with go-micro.Service
|
||||
func NewService(opts ...micro.Option) micro.Service {
|
||||
func NewService(opts ...service.Option) service.Service {
|
||||
// our grpc client
|
||||
c := client.NewClient()
|
||||
c := gclient.NewClient()
|
||||
// our grpc server
|
||||
s := server.NewServer()
|
||||
// our grpc broker
|
||||
b := broker.NewBroker()
|
||||
s := gserver.NewServer()
|
||||
|
||||
// create options with priority for our opts
|
||||
options := []micro.Option{
|
||||
micro.Client(c),
|
||||
micro.Server(s),
|
||||
micro.Broker(b),
|
||||
options := []service.Option{
|
||||
service.Client(c),
|
||||
service.Server(s),
|
||||
}
|
||||
|
||||
// append passed in opts
|
||||
options = append(options, opts...)
|
||||
|
||||
// generate and return a service
|
||||
return micro.NewService(options...)
|
||||
}
|
||||
|
||||
// NewFunction returns a grpc service compatible with go-micro.Function
|
||||
func NewFunction(opts ...micro.Option) micro.Function {
|
||||
// our grpc client
|
||||
c := client.NewClient()
|
||||
// our grpc server
|
||||
s := server.NewServer()
|
||||
// our grpc broker
|
||||
b := broker.NewBroker()
|
||||
|
||||
// create options with priority for our opts
|
||||
options := []micro.Option{
|
||||
micro.Client(c),
|
||||
micro.Server(s),
|
||||
micro.Broker(b),
|
||||
micro.RegisterTTL(time.Minute),
|
||||
micro.RegisterInterval(time.Second * 30),
|
||||
}
|
||||
|
||||
// append passed in opts
|
||||
options = append(options, opts...)
|
||||
|
||||
// generate and return a function
|
||||
return micro.NewFunction(options...)
|
||||
return newService(options...)
|
||||
}
|
||||
|
@@ -7,8 +7,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro"
|
||||
"github.com/micro/go-micro/registry/memory"
|
||||
"github.com/micro/go-micro/service"
|
||||
hello "github.com/micro/go-micro/service/grpc/proto"
|
||||
mls "github.com/micro/go-micro/util/tls"
|
||||
)
|
||||
@@ -32,13 +32,13 @@ func TestGRPCService(t *testing.T) {
|
||||
|
||||
// create GRPC service
|
||||
service := NewService(
|
||||
micro.Name("test.service"),
|
||||
micro.Registry(r),
|
||||
micro.AfterStart(func() error {
|
||||
service.Name("test.service"),
|
||||
service.Registry(r),
|
||||
service.AfterStart(func() error {
|
||||
wg.Done()
|
||||
return nil
|
||||
}),
|
||||
micro.Context(ctx),
|
||||
service.Context(ctx),
|
||||
)
|
||||
|
||||
// register test handler
|
||||
@@ -81,50 +81,6 @@ func TestGRPCService(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGRPCFunction(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// create service
|
||||
fn := NewFunction(
|
||||
micro.Name("test.function"),
|
||||
micro.Registry(memory.NewRegistry()),
|
||||
micro.AfterStart(func() error {
|
||||
wg.Done()
|
||||
return nil
|
||||
}),
|
||||
micro.Context(ctx),
|
||||
)
|
||||
|
||||
// register test handler
|
||||
hello.RegisterTestHandler(fn.Server(), &testHandler{})
|
||||
|
||||
// run service
|
||||
go fn.Run()
|
||||
|
||||
// wait for start
|
||||
wg.Wait()
|
||||
|
||||
// create client
|
||||
test := hello.NewTestService("test.function", fn.Client())
|
||||
|
||||
// call service
|
||||
rsp, err := test.Call(context.Background(), &hello.Request{
|
||||
Name: "John",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// check message
|
||||
if rsp.Msg != "Hello John" {
|
||||
t.Fatalf("unexpected response %s", rsp.Msg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGRPCTLSService(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
@@ -147,13 +103,13 @@ func TestGRPCTLSService(t *testing.T) {
|
||||
|
||||
// create GRPC service
|
||||
service := NewService(
|
||||
micro.Name("test.service"),
|
||||
micro.Registry(r),
|
||||
micro.AfterStart(func() error {
|
||||
service.Name("test.service"),
|
||||
service.Registry(r),
|
||||
service.AfterStart(func() error {
|
||||
wg.Done()
|
||||
return nil
|
||||
}),
|
||||
micro.Context(ctx),
|
||||
service.Context(ctx),
|
||||
// set TLS config
|
||||
WithTLS(config),
|
||||
)
|
||||
|
@@ -3,14 +3,14 @@ package grpc
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/micro/go-micro"
|
||||
gc "github.com/micro/go-micro/client/grpc"
|
||||
gs "github.com/micro/go-micro/server/grpc"
|
||||
"github.com/micro/go-micro/service"
|
||||
)
|
||||
|
||||
// WithTLS sets the TLS config for the service
|
||||
func WithTLS(t *tls.Config) micro.Option {
|
||||
return func(o *micro.Options) {
|
||||
func WithTLS(t *tls.Config) service.Option {
|
||||
return func(o *service.Options) {
|
||||
o.Client.Init(
|
||||
gc.AuthTLS(t),
|
||||
)
|
||||
|
@@ -2,20 +2,116 @@
|
||||
package mucp
|
||||
|
||||
import (
|
||||
// TODO: change to go-micro/service
|
||||
"github.com/micro/go-micro"
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/server"
|
||||
cmucp "github.com/micro/go-micro/client/mucp"
|
||||
smucp "github.com/micro/go-micro/server/mucp"
|
||||
"github.com/micro/go-micro/service"
|
||||
)
|
||||
|
||||
type mucpService struct {
|
||||
opts service.Options
|
||||
}
|
||||
|
||||
func newService(opts ...service.Option) service.Service {
|
||||
options := service.NewOptions(opts...)
|
||||
|
||||
return &mucpService{
|
||||
opts: options,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *mucpService) Name() string {
|
||||
return s.opts.Server.Options().Name
|
||||
}
|
||||
|
||||
// Init initialises options. Additionally it calls cmd.Init
|
||||
// which parses command line flags. cmd.Init is only called
|
||||
// on first Init.
|
||||
func (s *mucpService) Init(opts ...service.Option) {
|
||||
// process options
|
||||
for _, o := range opts {
|
||||
o(&s.opts)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *mucpService) Options() service.Options {
|
||||
return s.opts
|
||||
}
|
||||
|
||||
func (s *mucpService) Client() client.Client {
|
||||
return s.opts.Client
|
||||
}
|
||||
|
||||
func (s *mucpService) Server() server.Server {
|
||||
return s.opts.Server
|
||||
}
|
||||
|
||||
func (s *mucpService) String() string {
|
||||
return "mucp"
|
||||
}
|
||||
|
||||
func (s *mucpService) Start() error {
|
||||
for _, fn := range s.opts.BeforeStart {
|
||||
if err := fn(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.opts.Server.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, fn := range s.opts.AfterStart {
|
||||
if err := fn(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *mucpService) Stop() error {
|
||||
var gerr error
|
||||
|
||||
for _, fn := range s.opts.BeforeStop {
|
||||
if err := fn(); err != nil {
|
||||
gerr = err
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.opts.Server.Stop(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, fn := range s.opts.AfterStop {
|
||||
if err := fn(); err != nil {
|
||||
gerr = err
|
||||
}
|
||||
}
|
||||
|
||||
return gerr
|
||||
}
|
||||
|
||||
func (s *mucpService) Run() error {
|
||||
if err := s.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// wait on context cancel
|
||||
<-s.opts.Context.Done()
|
||||
|
||||
return s.Stop()
|
||||
}
|
||||
|
||||
// NewService returns a new mucp service
|
||||
func NewService(opts ...micro.Option) micro.Service {
|
||||
options := []micro.Option{
|
||||
micro.Client(cmucp.NewClient()),
|
||||
micro.Server(smucp.NewServer()),
|
||||
func NewService(opts ...service.Option) service.Service {
|
||||
options := []service.Option{
|
||||
service.Client(cmucp.NewClient()),
|
||||
service.Server(smucp.NewServer()),
|
||||
}
|
||||
|
||||
options = append(options, opts...)
|
||||
|
||||
return micro.NewService(options...)
|
||||
return newService(options...)
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ type Options struct {
|
||||
|
||||
type Option func(*Options)
|
||||
|
||||
func newOptions(opts ...Option) Options {
|
||||
func NewOptions(opts ...Option) Options {
|
||||
opt := Options{
|
||||
Broker: broker.DefaultBroker,
|
||||
Client: client.DefaultClient,
|
||||
|
Reference in New Issue
Block a user