Each time gate RPC calls (message) game, game will synchronously call RPC (send) gate to push the same message.
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.
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"
}
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:
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)
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.
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))
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
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))
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
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
Switch to webside directory and open index.html (Chrome browser is recommended)
Pls. refer to HOWTO.md under the root directory to run this sample.