You can combine the PHP and Golang GRPC services within one application.
Make sure to read how to build application server.
To demonstrate the ability to register Golang GRPC service define the proto file with needed agreements:
syntax = "proto3";
package multiplier;
message Mult {
int32 a = 1;
int32 b = 2;
}
message MultResult {
int32 result = 1;
}
service Multiplier {
rpc Mult (multiplier.Mult) returns (multiplier.MultResult) {
}
}
Generate the server code in multiplier
folder:
$ mkdir multiplier
$ protoc -I proto/ proto/multiplier.proto --go_out=plugins=grpc:multiplier
Make sure to install
protoc-gen-go
. Read about installation here.
Create RoadRunner compatible service in multipler directory. To register GRPC service request the *grpc.Service
dependency
and invoke AddService
:
package multiplier
import (
"context"
grpc "github.com/spiral/php-grpc"
grpc2 "google.golang.org/grpc"
)
const ID = "multiplier"
type Service struct {
}
func (s *Service) Init(g *grpc.Service) (bool, error) {
return true, g.AddService(func(server *grpc2.Server) {
RegisterMultiplierServer(server, s)
})
}
func (s *Service) Mult(ctx context.Context, in *Mult) (*MultResult, error) {
return &MultResult{Result: in.A * in.B}, nil
}
To activate the service make sure to create and build custom application server:
$ go mod init demo
$ go get google.golang.org/grpc
Make sure to request proper dependencies in go.mod
:
module demo
require (
github.com/golang/protobuf v1.3.2
github.com/spiral/broadcast v0.0.0-20191206140608-766959683e74
github.com/spiral/broadcast-ws v1.1.0
github.com/spiral/jobs v2.1.3
github.com/spiral/php-grpc v1.2.0
github.com/spiral/roadrunner v1.6.2
google.golang.org/genproto v0.0.0-20181016170114-94acd270e44e
google.golang.org/grpc v1.21.0
)
Modify the main.go
to activate the service:
package main
import (
"demo/multiplier"
rr "github.com/spiral/roadrunner/cmd/rr/cmd"
// services (plugins)
"github.com/spiral/broadcast"
"github.com/spiral/broadcast-ws"
"github.com/spiral/jobs/v2"
"github.com/spiral/php-grpc"
"github.com/spiral/roadrunner/service/env"
"github.com/spiral/roadrunner/service/headers"
"github.com/spiral/roadrunner/service/health"
"github.com/spiral/roadrunner/service/http"
"github.com/spiral/roadrunner/service/limit"
"github.com/spiral/roadrunner/service/metrics"
"github.com/spiral/roadrunner/service/reload"
"github.com/spiral/roadrunner/service/rpc"
"github.com/spiral/roadrunner/service/static"
// queue brokers
"github.com/spiral/jobs/v2/broker/amqp"
"github.com/spiral/jobs/v2/broker/beanstalk"
"github.com/spiral/jobs/v2/broker/ephemeral"
"github.com/spiral/jobs/v2/broker/sqs"
// additional commands and debug handlers
_ "github.com/spiral/broadcast-ws/cmd/rr-ws/ws"
_ "github.com/spiral/jobs/v2/cmd/rr-jobs/jobs"
_ "github.com/spiral/php-grpc/cmd/rr-grpc/grpc"
_ "github.com/spiral/roadrunner/cmd/rr/http"
_ "github.com/spiral/roadrunner/cmd/rr/limit"
)
func main() {
rr.Container.Register(env.ID, &env.Service{})
rr.Container.Register(rpc.ID, &rpc.Service{})
// http
rr.Container.Register(http.ID, &http.Service{})
rr.Container.Register(headers.ID, &headers.Service{})
rr.Container.Register(static.ID, &static.Service{})
rr.Container.Register(grpc.ID, &grpc.Service{})
rr.Container.Register(jobs.ID, &jobs.Service{
Brokers: map[string]jobs.Broker{
"amqp": &amqp.Broker{},
"ephemeral": &ephemeral.Broker{},
"beanstalk": &beanstalk.Broker{},
"sqs": &sqs.Broker{},
},
})
// pub-sub
rr.Container.Register(broadcast.ID, &broadcast.Service{})
rr.Container.Register(ws.ID, &ws.Service{})
// supervisor and metrics
rr.Container.Register(limit.ID, &limit.Service{})
rr.Container.Register(metrics.ID, &metrics.Service{})
rr.Container.Register(health.ID, &health.Service{})
// auto reloading
rr.Container.Register(reload.ID, &reload.Service{})
rr.Container.Register(multiplier.ID, &multiplier.Service{})
// you can register additional commands using cmd.CLI
rr.Execute()
}
You can run the server now:
$ go run main.go serve -v -d
Read here how to implement streaming and batch processing using hybrid PHP/Go approach.