go-micro.dev/v5@v5.12.0/internal/website/docs/guides/migration/from-grpc.md (about) 1 --- 2 layout: default 3 --- 4 5 # Migrating from gRPC 6 7 Step-by-step guide to migrating existing gRPC services to Go Micro. 8 9 ## Why Migrate? 10 11 Go Micro adds: 12 - Built-in service discovery 13 - Client-side load balancing 14 - Pub/sub messaging 15 - Multiple transport options 16 - Unified tooling 17 18 You keep: 19 - Your proto definitions 20 - gRPC performance (via gRPC transport) 21 - Type safety 22 - Streaming support 23 24 ## Migration Strategy 25 26 ### Phase 1: Parallel Running 27 Run Go Micro alongside existing gRPC services 28 29 ### Phase 2: Gradual Migration 30 Migrate services one at a time 31 32 ### Phase 3: Complete Migration 33 All services on Go Micro 34 35 ## Step-by-Step Migration 36 37 ### 1. Existing gRPC Service 38 39 ```protobuf 40 // proto/hello.proto 41 syntax = "proto3"; 42 43 package hello; 44 option go_package = "./proto;hello"; 45 46 service Greeter { 47 rpc SayHello (HelloRequest) returns (HelloReply) {} 48 } 49 50 message HelloRequest { 51 string name = 1; 52 } 53 54 message HelloReply { 55 string message = 1; 56 } 57 ``` 58 59 ```go 60 // Original gRPC server 61 package main 62 63 import ( 64 "context" 65 "log" 66 "net" 67 "google.golang.org/grpc" 68 pb "myapp/proto" 69 ) 70 71 type server struct { 72 pb.UnimplementedGreeterServer 73 } 74 75 func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) { 76 return &pb.HelloReply{Message: "Hello " + req.Name}, nil 77 } 78 79 func main() { 80 lis, _ := net.Listen("tcp", ":50051") 81 s := grpc.NewServer() 82 pb.RegisterGreeterServer(s, &server{}) 83 log.Fatal(s.Serve(lis)) 84 } 85 ``` 86 87 ### 2. Generate Go Micro Code 88 89 Update your proto generation: 90 91 ```bash 92 # Install protoc-gen-micro 93 go install go-micro.dev/v5/cmd/protoc-gen-micro@latest 94 95 # Generate both gRPC and Go Micro code 96 protoc --proto_path=. \ 97 --go_out=. --go_opt=paths=source_relative \ 98 --go-grpc_out=. --go-grpc_opt=paths=source_relative \ 99 --micro_out=. --micro_opt=paths=source_relative \ 100 proto/hello.proto 101 ``` 102 103 This generates: 104 - `hello.pb.go` - Protocol Buffers types 105 - `hello_grpc.pb.go` - gRPC client/server (keep for compatibility) 106 - `hello.pb.micro.go` - Go Micro client/server (new) 107 108 ### 3. Migrate Server to Go Micro 109 110 ```go 111 // Go Micro server 112 package main 113 114 import ( 115 "context" 116 "go-micro.dev/v5" 117 "go-micro.dev/v5/server" 118 pb "myapp/proto" 119 ) 120 121 type Greeter struct{} 122 123 func (s *Greeter) SayHello(ctx context.Context, req *pb.HelloRequest, rsp *pb.HelloReply) error { 124 rsp.Message = "Hello " + req.Name 125 return nil 126 } 127 128 func main() { 129 svc := micro.NewService( 130 micro.Name("greeter"), 131 ) 132 svc.Init() 133 134 pb.RegisterGreeterHandler(svc.Server(), new(Greeter)) 135 136 if err := svc.Run(); err != nil { 137 log.Fatal(err) 138 } 139 } 140 ``` 141 142 **Key differences:** 143 - No manual port binding (Go Micro handles it) 144 - Automatic service registration 145 - Returns error, response via pointer parameter 146 147 ### 4. Migrate Client 148 149 **Original gRPC client:** 150 ```go 151 conn, _ := grpc.Dial("localhost:50051", grpc.WithInsecure()) 152 defer conn.Close() 153 154 client := pb.NewGreeterClient(conn) 155 rsp, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "John"}) 156 ``` 157 158 **Go Micro client:** 159 ```go 160 svc := micro.NewService(micro.Name("client")) 161 svc.Init() 162 163 client := pb.NewGreeterService("greeter", svc.Client()) 164 rsp, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "John"}) 165 ``` 166 167 **Benefits:** 168 - No hardcoded addresses 169 - Automatic service discovery 170 - Client-side load balancing 171 - Automatic retries 172 173 ### 5. Keep gRPC Transport (Optional) 174 175 Use gRPC as the underlying transport: 176 177 ```go 178 import ( 179 "go-micro.dev/v5" 180 "go-micro.dev/v5/client" 181 "go-micro.dev/v5/server" 182 grpcclient "go-micro.dev/v5/client/grpc" 183 grpcserver "go-micro.dev/v5/server/grpc" 184 ) 185 186 svc := micro.NewService( 187 micro.Name("greeter"), 188 micro.Client(grpcclient.NewClient()), 189 micro.Server(grpcserver.NewServer()), 190 ) 191 ``` 192 193 This gives you: 194 - gRPC performance 195 - Go Micro features (discovery, load balancing) 196 - Compatible with existing gRPC clients 197 198 ## Streaming Migration 199 200 ### Original gRPC Streaming 201 202 ```protobuf 203 service Greeter { 204 rpc StreamHellos (stream HelloRequest) returns (stream HelloReply) {} 205 } 206 ``` 207 208 ```go 209 func (s *server) StreamHellos(stream pb.Greeter_StreamHellosServer) error { 210 for { 211 req, err := stream.Recv() 212 if err == io.EOF { 213 return nil 214 } 215 if err != nil { 216 return err 217 } 218 219 stream.Send(&pb.HelloReply{Message: "Hello " + req.Name}) 220 } 221 } 222 ``` 223 224 ### Go Micro Streaming 225 226 ```go 227 func (s *Greeter) StreamHellos(ctx context.Context, stream server.Stream) error { 228 for { 229 var req pb.HelloRequest 230 if err := stream.Recv(&req); err != nil { 231 return err 232 } 233 234 if err := stream.Send(&pb.HelloReply{Message: "Hello " + req.Name}); err != nil { 235 return err 236 } 237 } 238 } 239 ``` 240 241 ## Service Discovery Migration 242 243 ### Before (gRPC with Consul) 244 245 ```go 246 // Manually register with Consul 247 config := api.DefaultConfig() 248 config.Address = "consul:8500" 249 client, _ := api.NewClient(config) 250 251 reg := &api.AgentServiceRegistration{ 252 ID: "greeter-1", 253 Name: "greeter", 254 Address: "localhost", 255 Port: 50051, 256 } 257 client.Agent().ServiceRegister(reg) 258 259 // Cleanup on shutdown 260 defer client.Agent().ServiceDeregister("greeter-1") 261 ``` 262 263 ### After (Go Micro) 264 265 ```go 266 import "go-micro.dev/v5/registry/consul" 267 268 reg := consul.NewConsulRegistry() 269 svc := micro.NewService( 270 micro.Name("greeter"), 271 micro.Registry(reg), 272 ) 273 274 // Registration automatic on Run() 275 // Deregistration automatic on shutdown 276 svc.Run() 277 ``` 278 279 ## Load Balancing Migration 280 281 ### Before (gRPC with custom LB) 282 283 ```go 284 // Need external load balancer or custom implementation 285 // Example: round-robin DNS, Envoy, nginx 286 ``` 287 288 ### After (Go Micro) 289 290 ```go 291 import "go-micro.dev/v5/selector" 292 293 // Client-side load balancing built-in 294 svc := micro.NewService( 295 micro.Selector(selector.NewSelector( 296 selector.SetStrategy(selector.RoundRobin), 297 )), 298 ) 299 ``` 300 301 ## Gradual Migration Path 302 303 ### 1. Start with New Services 304 305 New services use Go Micro, existing services stay on gRPC. 306 307 ```go 308 // New Go Micro service can call gRPC services 309 // Configure gRPC endpoints directly 310 grpcConn, _ := grpc.Dial("old-service:50051", grpc.WithInsecure()) 311 oldClient := pb.NewOldServiceClient(grpcConn) 312 ``` 313 314 ### 2. Migrate Read-Heavy Services First 315 316 Services with many clients benefit most from service discovery. 317 318 ### 3. Migrate Services with Fewest Dependencies 319 320 Leaf services are easier to migrate. 321 322 ### 4. Add Adapters if Needed 323 324 ```go 325 // gRPC adapter for Go Micro service 326 type GRPCAdapter struct { 327 microClient pb.GreeterService 328 } 329 330 func (a *GRPCAdapter) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) { 331 return a.microClient.SayHello(ctx, req) 332 } 333 334 // Register adapter as gRPC server 335 s := grpc.NewServer() 336 pb.RegisterGreeterServer(s, &GRPCAdapter{microClient: microClient}) 337 ``` 338 339 ## Checklist 340 341 - [ ] Update proto generation to include `--micro_out` 342 - [ ] Convert handler signatures (response via pointer) 343 - [ ] Replace `grpc.Dial` with Go Micro client 344 - [ ] Configure service discovery (Consul, Etcd, etc) 345 - [ ] Update deployment (remove hardcoded ports) 346 - [ ] Update monitoring (Go Micro metrics) 347 - [ ] Test service-to-service communication 348 - [ ] Update documentation 349 - [ ] Train team on Go Micro patterns 350 351 ## Common Issues 352 353 ### Port Already in Use 354 355 **gRPC**: Manual port management 356 ```go 357 lis, _ := net.Listen("tcp", ":50051") 358 ``` 359 360 **Go Micro**: Automatic or explicit 361 ```go 362 // Let Go Micro choose 363 svc := micro.NewService(micro.Name("greeter")) 364 365 // Or specify 366 svc := micro.NewService( 367 micro.Name("greeter"), 368 micro.Address(":50051"), 369 ) 370 ``` 371 372 ### Service Not Found 373 374 Check registry: 375 ```bash 376 # Consul 377 curl http://localhost:8500/v1/catalog/services 378 379 # Or use micro CLI 380 micro services 381 ``` 382 383 ### Different Serialization 384 385 gRPC uses protobuf by default. Go Micro supports multiple codecs. 386 387 Ensure both use protobuf: 388 ```go 389 import "go-micro.dev/v5/codec/proto" 390 391 svc := micro.NewService( 392 micro.Codec("application/protobuf", proto.Marshaler{}), 393 ) 394 ``` 395 396 ## Performance Comparison 397 398 | Scenario | gRPC | Go Micro (HTTP) | Go Micro (gRPC) | 399 |----------|------|----------------|-----------------| 400 | Simple RPC | ~25k req/s | ~20k req/s | ~24k req/s | 401 | With Discovery | N/A | ~18k req/s | ~22k req/s | 402 | Streaming | ~30k msg/s | ~15k msg/s | ~28k msg/s | 403 404 *Go Micro with gRPC transport performs similarly to pure gRPC* 405 406 ## Next Steps 407 408 - Read [Go Micro Architecture](../architecture.md) 409 - Explore [Plugin System](../plugins.md) 410 - Check [Production Patterns](../examples/realworld/) 411 412 ## Need Help? 413 414 - [Examples](../examples/) 415 - [GitHub Issues](https://github.com/micro/go-micro/issues) 416 - [API Documentation](https://pkg.go.dev/go-micro.dev/v5)