Microservice
In the previous article, we have demonstrated how to quickly create a monolithic service. Next, let’s demonstrate how to quickly create a microservice. In this section, the api part is actually the same as the creation logic of the monolithic service, except that there is no communication between services in the monolithic service. And the api service in the microservice will have more rpc call configuration.
This section will briefly demonstrate with an calling user service
. The demo code only conveys ideas, and some links will not be listed one by one.
Scenario summary
Suppose we are developing a mall project, and the developer Xiao Ming is responsible for the development of the user module (user) and the order module (order). Let’s split these two modules into two microservices.①
- Order service (order) provides a query interface
- User service (user) provides a method for order service to obtain user information
Service design analysis
According to the scenario summary, we can know that the order is directly facing the user, and the data is accessed through the http protocol, and some basic data of the user needs to be obtained inside the order. Since our service adopts the microservice architecture design, Then two services (user, order) must exchange data. The data exchange between services is the communication between services. At this point, it is also a developer’s need to adopt a reasonable communication protocol. For consideration, communication can be carried out through http, rpc and other methods. Here we choose rpc to implement communication between services. I believe that I have already made a better scenario description of “What is the role of rpc service?”. Of course, there is much more than this design analysis before a service is developed, and we will not describe it in detail here. From the above, we need:
- user rpc
- order api
two services to initially implement this small demo.
Create user rpc service
-
$ cd ~/go-zero-demo/mall
$ mkdir -p user/rpc&&cd user/rpc
Add
user.proto
file, addgetUser
method$ vim ~/go-zero-demo/mall/user/user.proto
syntax = "proto3";
package user;
message IdRequest {
string id = 1;
}
message UserResponse {
string id = 1;
string name = 2;
string gender = 3;
}
service User {
rpc getUser(IdRequest) returns(UserResponse);
}
Generate code
$ cd ~/go-zero-demo/mall/user/rpc
$ goctl rpc proto -src user.proto -dir .
protoc -I=/Users/xx/mall/user user.proto --go_out=plugins=grpc:/Users/xx/mall/user/user
Done.
Fill in business logic
$ vim internal/logic/getuserlogic.go
package logic
import (
"context"
"go-zero-demo/mall/user/internal/svc"
"go-zero-demo/mall/user/user"
"github.com/tal-tech/go-zero/core/logx"
type GetUserLogic struct {
ctx context.Context
logx.Logger
}
func NewGetUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserLogic {
return &GetUserLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
func (l *GetUserLogic) GetUser(in *user.IdRequest) (*user.UserResponse, error) {
return &user.UserResponse{
Id: "1",
Name: "test",
}, nil
}
Create an
order api
service$ cd ~/go-zero-demo/mall
$ mkdir -p order/api&&cd order/api
Add api file
type(
OrderReq {
Id string `path:"id"`
}
OrderReply {
Id string `json:"id"`
Name string `json:"name"`
}
)
service order {
@handler getOrder
get /api/order/get/:id (OrderReq) returns (OrderReply)
}
- Generate
order
service$ goctl api go -api order.api -dir .
Done.
Add user rpc configuration
$ vim internal/config/config.go
package config
import "github.com/tal-tech/go-zero/rest"
type Config struct {
rest.RestConf
UserRpc zrpc.RpcClientConf
-
$ vim etc/order.yaml
Name: order
Host: 0.0.0.0
Port: 8888
UserRpc:
Etcd:
Hosts:
- 127.0.0.1:2379
Key: user.rpc
Improve service dependence
$ vim internal/svc/servicecontext.go
Add order demo logic
Add business logic to
getorderlogic
$ vim ~/go-zero-demo/mall/order/api/internal/logic/getorderlogic.go
user, err := l.svcCtx.UserRpc.GetUser(l.ctx, &userclient.IdRequest{
Id: "1",
})
if err != nil {
return nil, err
}
if user.Name != "test" {
return nil, errors.New("User does not exist")
}
return &types.OrderReply{
Id: req.Id,
Name: "test order",
}, nil
Start the service and verify
- Start etcd
$ etcd
Start user rpc
$ go run user.go -f etc/user.yaml
Starting rpc server at 127.0.0.1:8080...
Start order api
$ go run order.go -f etc/order.yaml
Starting server at 0.0.0.0:8888...
Access order api
HTTP/1.1 200 OK
Content-Type: application/json
Date: Sun, 07 Feb 2021 03:45:05 GMT
Content-Length: 30
{"id":"1","name":"test order"}