Microservices

[!TIP] This document is machine-translated by Google. If you find grammatical and semantic errors, and the document description is not clear, please PR

In the previous article we have shown how to quickly create a single service, next we will show how to quickly create a microservice. In this section, the api part is actually the same as the creation logic of a monolithic service, except that there is no inter-service communication in the monolithic service. In this section, the api part is actually the same logic as 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 configuration for rpc calls.

Preface

This section will be a simple demonstration of an order service to call the user service, the demo code only to pass the idea, some of the links will not be enumerated.

Scenario Summary

Suppose we are developing a mall project, and the developer Xiaoming is responsible for the development of the user module (user) and the order module (order), let’s split these two modules into two microservices ①

[!NOTE] ①: The splitting of microservices is also a learning curve, so we won’t discuss the details of how to split microservices here.

Demonstrate functional goals

  • Order service(order) provides a query interface
  • user service (user) provides a method for the order service to obtain user information

Service Design Analysis

According to the scenario synopsis we can learn that the order is directly user-oriented, accessing data through the http protocol, and the order internal need to obtain some basic data about the user, since our service is designed using the microservices architecture. Then the two services (user,order) must exchange data, the data exchange between services that is, the communication between services, to here, the use of a reasonable communication protocol is also a developer needs to Here we choose rpc to realize the communication between services, and I believe I have already made a better scenario of “What is the role of rpc service? I believe I have already described a good scenario here. Of course, there is much more to a service than just design analysis before development, so we won’t go into detail here. From the above, we know that we need a

  • user rpc
  • order api

two services to initially implement this little demo.

Create mall project

If you run the monolithic example, which is also called go-zero-demo, you may need to change the parent directory.

  1. $ mkdir go-zero-demo
  2. $ cd go-zero-demo
  3. $ go mod init go-zero-demo

Note: If there is no cd operation to change the directory, all operations are performed in the `go-zero-demo directory

Create user rpc service

  • Create the user rpc service

    1. $ mkdir -p mall/user/rpc
  • Add user.proto file, add getUser method

    1. $ vim mall/user/rpc/user.proto

    Add the following code.

    1. syntax = "proto3";
    2. package user;
    3. // protoc-gen-go version is greater than 1.4.0, proto file needs to add go_package, otherwise it can't be generated
    4. option go_package = "./user";
    5. message IdRequest {
    6. string id = 1;
    7. }
    8. message UserResponse {
    9. // user id
    10. string id = 1;
    11. // user name
    12. string name = 2;
    13. // user gender
    14. string gender = 3;
    15. }
    16. service User {
    17. rpc getUser(IdRequest) returns(UserResponse);
    18. }
  • Generate the code

    1. $ cd mall/user/rpc
    2. $ goctl rpc protoc user.proto --go_out=./types --go-grpc_out=./types --zrpc_out=.
    3. Done.

[!TIPS] grpc directive details refer to https://grpc.io/docs/languages/go/quickstart/

  • Padding business logic

    1. $ vim internal/logic/getuserlogic.go
    1. package logic
    2. import (
    3. "context"
    4. "go-zero-demo/mall/user/rpc/internal/svc"
    5. "go-zero-demo/mall/user/rpc/types/user"
    6. "github.com/zeromicro/go-zero/core/logx"
    7. )
    8. type GetUserLogic struct {
    9. ctx context.Context
    10. svcCtx *svc.ServiceContext
    11. logx.Logger
    12. }
    13. func NewGetUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserLogic {
    14. return &GetUserLogic{
    15. ctx: ctx,
    16. svcCtx: svcCtx,
    17. Logger: logx.WithContext(ctx),
    18. }
    19. }
    20. func (l *GetUserLogic) GetUser(in *user.IdRequest) (*user.UserResponse, error) {
    21. return &user.UserResponse{
    22. Id: "1",
    23. Name: "test",
    24. }, nil
    25. }

Create order api service

  • Create order api service

    1. # in dir go-zero-demo/mall
    2. $ mkdir -p order/api && cd order/api
  • Add api file

    1. $ vim order.api
    1. type(
    2. OrderReq {
    3. Id string `path:"id"`
    4. }
    5. OrderReply {
    6. Id string `json:"id"`
    7. Name string `json:"name"`
    8. }
    9. )
    10. service order {
    11. @handler getOrder
    12. get /api/order/get/:id (OrderReq) returns (OrderReply)
    13. }
  • Generate the order service

    1. $ goctl api go -api order.api -dir .
    2. Done.
  • Add user rpc configuration

    1. $ vim internal/config/config.go
    1. package config
    2. import (
    3. "github.com/zeromicro/go-zero/zrpc"
    4. "github.com/zeromicro/go-zero/rest"
    5. )
    6. type Config struct {
    7. rest.RestConf
    8. UserRpc zrpc.RpcClientConf
    9. }
  • Add yaml configuration

    1. $ vim etc/order.yaml
    1. Name: order
    2. Host: 0.0.0.0
    3. Port: 8888
    4. UserRpc:
    5. Etcd:
    6. Hosts:
    7. - 127.0.0.1:2379
    8. Key: user.rpc
  • refine the service dependencies

    1. $ vim internal/svc/servicecontext.go
    1. package svc
    2. import (
    3. "go-zero-demo/mall/order/api/internal/config"
    4. "go-zero-demo/mall/user/rpc/user"
    5. "github.com/zeromicro/go-zero/zrpc"
    6. )
    7. type ServiceContext struct {
    8. Config config.Config
    9. UserRpc user.User
    10. }
    11. func NewServiceContext(c config.Config) *ServiceContext {
    12. return &ServiceContext{
    13. Config: c,
    14. UserRpc: user.NewUser(zrpc.MustNewClient(c.UserRpc)),
    15. }
    16. }
  • Adding order demo logic

    Add business logic to getorderlogic

    1. $ vim internal/logic/getorderlogic.go
    1. package logic
    2. import (
    3. "context"
    4. "errors"
    5. "go-zero-demo/mall/order/api/internal/svc"
    6. "go-zero-demo/mall/order/api/internal/types"
    7. "go-zero-demo/mall/user/rpc/types/user"
    8. "github.com/zeromicro/go-zero/core/logx"
    9. )
    10. type GetOrderLogic struct {
    11. logx.Logger
    12. ctx context.Context
    13. svcCtx *svc.ServiceContext
    14. }
    15. func NewGetOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) GetOrderLogic {
    16. return GetOrderLogic{
    17. Logger: logx.WithContext(ctx),
    18. ctx: ctx,
    19. svcCtx: svcCtx,
    20. }
    21. }
    22. func (l *GetOrderLogic) GetOrder(req types.OrderReq) (*types.OrderReply, error) {
    23. user, err := l.svcCtx.UserRpc.GetUser(l.ctx, &user.IdRequest{
    24. Id: "1",
    25. })
    26. if err != nil {
    27. return nil, err
    28. }
    29. if user.Name != "test" {
    30. return nil, errors.New("用户不存在")
    31. }
    32. return &types.OrderReply{
    33. Id: req.Id,
    34. Name: "test order",
    35. }, nil
    36. }

Start the service and verify

  • start etcd
    1. $ etcd
  • download dependencies
    1. # in dir go-zero-demo
    2. $ go mod tidy
  • start user rpc

    1. # in dir mall/user/rpc
    2. $ go run user.go -f etc/user.yaml
    3. Starting rpc server at 127.0.0.1:8080...
  • start order api

    1. # in dir mall/order/api
    2. $ go run order.go -f etc/order.yaml
    3. Starting server at 0.0.0.0:8888...
  • Accessing the order api

    1. curl -i -X GET http://localhost:8888/api/order/get/1
    2. HTTP/1.1 200 OK
    3. Content-Type: application/json
    4. Date: Sun, 07 Feb 2021 03:45:05 GMT
    5. Content-Length: 30
    6. {"id": "1", "name": "test order"}

[!TIP] The api syntax mentioned in the demo, rpc generation, goctl, goctl environment, etc. how to use and install, the quick start does not provide a detailed overview, we will have a detailed description of the subsequent documentation, you can also click the following [guess what you want to see] quick jump to see the corresponding documentation.

Source Code

mall source code

Guess what you want to see