tree: 8a122755adf9a91b612359ad402bb61c08f9eef7 [path history] [tgz]
  1. go-server-game/
  2. go-server-gate/
  3. pkg/
  4. website/
  5. README.md
  6. README_zh.md
game/README.md

Game Service Example

Backend

  • The example includes two services, gate (gateway service) and game (logical service)
  • The two services communicate with each other RPC (both registered provider and consumer)
  • The gate additionally starts the http service (port 8000), which is used to manually trigger the gate RPC to call game

Each time gate RPC calls (messagegame, game will synchronously call RPC (send) gate to push the same message.

outline

Catalog description

├── go-server-game    # game module
│   ├── cmd           # Main entrance
│   ├── conf          # configuration file
│   ├── docker        # docker-compose config file
│   ├── pkg           # provider and consumer
│   └── tests
├── go-server-gate    # gate module
│   ├── cmd           # Main entrance
│   ├── conf          # configuration file
│   ├── docker        # docker-compose config file
│   ├── pkg           # provider and consumer
│   └── tests
└── pkg
    ├── consumer      # public consumer
    │   ├── game
    │   └── gate
    └── pojo

Process of initiating HTTP service

From the perspective of consumer and provider, the process of initiating a call is as follows.

Game provides the basketball server and gate provides the HTTP server.

game module

server side

The server provides three services, message, online and offline. The code is as follows. The specific implementation can be in game/go-server-game/pkg/provider.go see in.

type BasketballService struct{}

func Login(ctx context.Context, data string) (*pojo.Result, error) {
    ...
}

func Score(ctx context.Context, uid, score string) (*pojo.Result, error) {
    ...
}

func Rank (ctx context.Context, uid string) (*pojo.Result, error) {
    ...
}

func (p *BasketballService) Reference() string {
    return "gameProvider.basketballService"
}
configuration file

Register the service in the configuration file, where gameProvider.basketballService Same as declared in the reference method.

services:
  "gameProvider.basketballService":
    registry: "demoZk"
    protocol: "dubbo"
    interface: "org.apache.dubbo.game.BasketballService"
    loadbalance: "random"
    warmup: "100"
    cluster: "failover"
    methods:
      - name: "Online"
        retries: 0
      - name: "Offline"
        retries: 0
      - name: "Message"
        retries: 

consumer side

The consumer of basketball is mainly used to be called by gate, so the main code is put in ‘game/pkg/consumer/gate/basketball.go’, The consumer code is as follows.

type BasketballService struct {
    Send func(ctx context.Context, uid string, data string) (*pojo.Result, error)
}

func (p *BasketballService) Reference() string {
    return "gateConsumer.basketballService"
}

In basketball, you only need to instantiate a consumer variable.

var gateBasketball = new(gate.BasketballService)

Then register to Dubbo go in main.

config.SetConsumerService(gateBasketball)
configuration file
references:
  "gateConsumer.basketballService":
    registry: "demoZk"
    protocol : "dubbo"
    interface : "org.apache.dubbo.gate.BasketballService"
    cluster: "failover"
    methods:
      - name: "Send"
        retries: 0

Because the consumer of game needs to call the provider of gate, the string returned by the reference method is gateConsumer.basketballService , in the configuration file gateConsumer.basketballService And ‘game/pkg/consumer/gate/basketball.go’. The value of interface should be consistent with that of the provider of gate.

gate module

server side

type BasketballService struct{}

func (p *BasketballService) Send(ctx context.Context, uid, data string) (*pojo.Result, error) {
...
}

func (p *BasketballService) Reference() string {
    return "gateProvider.basketballService"
}

Register with Dubbo

config.SetProviderService(new(BasketballService))
configuration file

gateProvider.basketballService The interface here must be the same as that in game client.yml The settings in the file should be consistent, otherwise game cannot send data to gate.

# service config
services:
  "gateProvider.basketballService":
    registry: "demoZk"
    protocol : "dubbo"
    interface : "org.apache.dubbo.gate.BasketballService"
    loadbalance: "random"
    warmup: "100"
    cluster: "failover"
    methods:
      - name: "Send"
        retries: 0

consumer side

The consumer side of the gate is relatively special. Because the consumer of the gate needs to call the service in the game, the consumer directly instantiates the service of a game, and its method directly uses the instantiated object gamebasketball to call, thus realizing the function of a gateway.

var GameBasketball = new(game.BasketballService)

func Login(ctx context.Context, data string) (*pojo.Result, error) {
    return GameBasketball.Login(ctx, data)
}

func Score(ctx context.Context, uid, score string) (*pojo.Result, error) {
    return GameBasketball.Score(ctx, uid, score)
}

func Rank (ctx context.Context, uid string) (*pojo.Result, error) {
    return GameBasketball.Rank(ctx, uid)
}

In code GameBasketball.Message、GameBasketball.Online、GameBasketball.Offline , all the methods called are game methods. Register with dubbo

config.SetProviderService(new(pkg.BasketballService))
configuration file

The inerface in the configuration file should also be consistent with the game provider, otherwise the gate cannot be called after receiving the HTTP request.

references:
  "gameConsumer.basketballService":
    registry: "demoZk"
    protocol : "dubbo"
    interface : "org.apache.dubbo.game.BasketballService"
    cluster: "failover"
    methods:
      - name: "Online"
        retries: 0
      - name: "Offline"
        retries: 0
      - name: "Message"
        retries: 0

HTTP access

access login

curl --location --request GET 'http://127.0.0.1:8089/login?name=dubbogo'

received

{
    "code": 0,
    "msg": "dubbogo, your score is 0",
    "data": {
        "score": 0,
        "to": "dubbogo"
    }
}

access score

curl --location --request POST 'http://127.0.0.1:8089/score' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name":"cjp",
    "score":1
}'

received

{
    "code": 0,
    "msg": "dubbogo, your score is 0",
    "data": {
        "score": 0,
        "to": "dubbogo"
    }
}

access rank

curl --location --request POST 'http://127.0.0.1:8089/rank?name=dubbogo'

received

{
    "code": 0,
    "msg": "success",
    "data": {
        "rank": 3,
        "to": "dubbogo"
    }
}

It can be found that all HTTP requests are successfully forwarded to game, and the processed data is returned to gate by calling the send method of gate

Start the front end

Switch to webside directory and open index.html (Chrome browser is recommended)

image-20210516173728198

Pls. refer to HOWTO.md under the root directory to run this sample.