Today we are going to do a fun Go practice. Start seven different Go Web frameworks simultaneously in one process, using the same set of code.

Why do such boring things?

The main purpose is to introduce the rookie Ninja/RK-boot library.

Which Go Web frameworks start?

We launched the following Go Web frameworks at the same time.

Web framework Fairly rk – the boot version
gin-gonic/gin go get github.com/rookie-ninja/rk-boot/gin V1.2.14 (Stable)
gRPC go get github.com/rookie-ninja/rk-boot/grpc V1.2.18 (Stable)
labstack/echo go get github.com/rookie-ninja/rk-boot/echo V0.0.8 (Stable)
gogf/gf go get github.com/rookie-ninja/rk-boot/gf V0.0.6 (Stable)
gofiber/fiber go get github.com/rookie-ninja/rk-boot/fiber V0.0.4 (Testing)
zeromicro/go-zero go get github.com/rookie-ninja/rk-boot/zero V0.0.2 (Testing)
gorilla/mux go get github.com/rookie-ninja/rk-boot/mux V0.0.2 (Testing)

Quick start

1. Install

We installed the following dependencies with Go Get.

go get github.com/rookie-ninja/rk-boot/grpc
go get github.com/rookie-ninja/rk-boot/gin
go get github.com/rookie-ninja/rk-boot/echo
go get github.com/rookie-ninja/rk-boot/gf
go get github.com/rookie-ninja/rk-boot/fiber
go get github.com/rookie-ninja/rk-boot/zero
go get github.com/rookie-ninja/rk-boot/mux
Copy the code

2. Create the boot. Yaml

Web framework port
gRPC 8081
gin-gonic/gin 8082
labstack/echo 8083
gogf/gf 8084
gofiber/fiber 8085
zeromicro/go-zero 8086
gorilla/mux 8087

In addition to specifying the port, we have enabled the following two options:

  • CommonService: Provides common apis such as/RK /v1/ HEALTHY.
  • LoggingZap: RPC log
---
grpc:
  - name: grpc
    port: 8081
    enabled: true
    commonService:
      enabled: true                   # Optional, default: false
    interceptors:
      loggingZap:
        enabled: true                 # Optional, default: false
gin:
  - name: gin
    port: 8082
    enabled: true
    commonService:
      enabled: true                   # Optional, default: false
    interceptors:
      loggingZap:
        enabled: true                 # Optional, default: false
echo:
  - name: echo
    port: 8083
    enabled: true
    commonService:
      enabled: true                   # Optional, default: false
    interceptors:
      loggingZap:
        enabled: true                 # Optional, default: false
gf:
  - name: gf
    port: 8084
    enabled: true
    commonService:
      enabled: true                   # Optional, default: false
    interceptors:
      loggingZap:
        enabled: true                 # Optional, default: false
fiber:
  - name: fiber
    port: 8085
    enabled: true
    commonService:
      enabled: true                   # Optional, default: false
    interceptors:
      loggingZap:
        enabled: true                 # Optional, default: false
zero:
  - name: zero
    port: 8086
    enabled: true
    commonService:
      enabled: true                   # Optional, default: false
    interceptors:
      loggingZap:
        enabled: true                 # Optional, default: false
mux:
  - name: mux
    port: 8087
    enabled: true
    commonService:
      enabled: true                   # Optional, default: false
    interceptors:
      loggingZap:
        enabled: true                 # Optional, default: false
Copy the code

3. Create a main. Go

All Web frameworks use the handleRequest() function to handle requests.

With the exception of gRPC, we did not use the protocol buffer, because PB has a different protocol. We use grPC-Gateway to simulate.

GrpcEntry default grpc-gateway, grpcentry. HttpMux to grpc-gateway API registration.

// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gofiber/adaptor/v2"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/labstack/echo/v4"
	"github.com/rookie-ninja/rk-boot"
	"github.com/rookie-ninja/rk-boot/echo"
	"github.com/rookie-ninja/rk-boot/fiber"
	"github.com/rookie-ninja/rk-boot/gf"
	"github.com/rookie-ninja/rk-boot/gin"
	"github.com/rookie-ninja/rk-boot/grpc"
	"github.com/rookie-ninja/rk-boot/mux"
	"github.com/rookie-ninja/rk-boot/zero"
	"github.com/tal-tech/go-zero/rest"
	"net/http"
)

const handlePath = "/v1/hello"

// Application entrance.
func main(a) {
	// Create a new boot instance.
	boot := rkboot.NewBoot()

	// 6: go-zero @8086, must adds route before bootstrap
	rkbootzero.GetZeroEntry("zero").Server.AddRoute(rest.Route{
		Method:  http.MethodGet,
		Path:    handlePath,
		Handler: handleRequest,
	})

	// Bootstrap
	boot.Bootstrap(context.Background())

	// 1: grpc-gateway @8081
	rkbootgrpc.GetGrpcEntry("grpc").HttpMux.HandleFunc(handlePath, handleRequest)
	// 2: gin @8082
	rkbootgin.GetGinEntry("gin").Router.Handle(http.MethodGet, handlePath, gin.WrapF(handleRequest))
	// 3: echo @8083
	rkbootecho.GetEchoEntry("echo").Echo.GET(handlePath, echo.WrapHandler(http.HandlerFunc(handleRequest)))
	// 4: GoFrame @8084
	rkbootgf.GetGfEntry("gf").Server.BindHandler(handlePath, ghttp.WrapF(handleRequest))
	// 5: Fiber @8085, must call RefreshFiberRoutes()
	rkbootfiber.GetFiberEntry("fiber").App.Get(handlePath, adaptor.HTTPHandler(http.HandlerFunc(handleRequest)))
	rkbootfiber.GetFiberEntry("fiber").RefreshFiberRoutes()
	// 7: mux @8087
	rkbootmux.GetMuxEntry("mux").Router.HandleFunc(handlePath, handleRequest)

	// Wait for shutdown sig
	boot.WaitForShutdownSig(context.Background())
}

// Handle request for all web frameworks
func handleRequest(writer http.ResponseWriter, req *http.Request) {
	// 1: get query
	name := req.URL.Query().Get("name")

	// 2: marshal response
	bytes, _ := json.Marshal(&Response{
		Message: fmt.Sprintf("Hello %s", name),
	})

	// 3: write response
	writer.WriteHeader(http.StatusOK)
	writer.Write(bytes)
}

type Response struct {
	Message string `json:"message"`
}
Copy the code

4. Folder structure & go.mod

  • Folder structure
.├ ── Go.tempo ├── go.tempo ├─ main. Go 0 directories, 4 filesCopy the code
  • Go. The mod file
1.16 the require module github.com/rookie-ninja/rk-demo go (github.com/gin-gonic/gin v1.7.7 github.com/gofiber/adaptor/v2 V2.1.15 github.com/gogf/gf/v2 v2.0.0 - beta github.com/labstack/echo/v4 v4.6.1 github.com/rookie-ninja/rk-boot v1.4.0 Github.com/rookie-ninja/rk-boot/echo v0.0.8 github.com/rookie-ninja/rk-boot/fiber v0.0.4 Github.com/rookie-ninja/rk-boot/gf v0.0.6 github.com/rookie-ninja/rk-boot/gin v1.2.14 Github.com/rookie-ninja/rk-boot/grpc v1.2.18 github.com/rookie-ninja/rk-boot/mux v0.0.2 github.com/rookie-ninja/rk-boot/zero v0.0.2 github.com/tal-tech/go-zero v1.2.4)Copy the code

5. Start the main. Go

$go run main.go 2022-01-03T19:15:14.016+0800 INFO boot/gf_entry.go:1050 Bootstrap gfEntry {"eventId": "264033ff-be9c-4147-871c-e4873ea1510d", "entryName": "Gf"} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- endTime = 2022-01-03 T19: mind. 016473 + 08:00 StartTime = 2022-01-03 T19: now. 016057 + 08:00 elapsedNano = 416178 timezone = CST ids={"eventId":"264033ff-be9c-4147-871c-e4873ea1510d"} app={"appName":"rk","appVersion":"","entryName":"gf","entryType":"GfEntry"} Env = {" arch ", "amd64", "az" : "*", "domain" : "*", "hostname" : "lark. Local", "localIP" : "10.8.0.2", "OS" : "Darwin", "realm" : "*", "region ":"*"} payloads={"commonServiceEnabled":true,"commonServicePathPrefix":"/rk/v1/","gfPort":8084} error={} counters={} pairs={} timing={} remoteAddr=localhost operation=Bootstrap resCode=OK eventStatus=Ended EOE ...Copy the code

Call /rk/v1/healthy to determine if the service is started.

$ curl localhost:8081/rk/v1/healthy
{"healthy":true}

$ curl localhost:8082/rk/v1/healthy
{"healthy":true}

$ curl localhost:8083/rk/v1/healthy
{"healthy":true}

$ curl localhost:8084/rk/v1/healthy
{"healthy":true}

$ curl localhost:8085/rk/v1/healthy
{"healthy":true}

$ curl localhost:8086/rk/v1/healthy
{"healthy":true}

$ curl localhost:8087/rk/v1/healthy
{"healthy":true}
Copy the code

6. Verify

We will send /v1/hello requests to each port and look at the RPC logs.

  • grpc-gateway@8081 (GRpc-gateway currently generates no RPC logs.)
$ curl "localhost:8081/v1/hello? name=rk-dev" {"message":"Hello rk-dev"}Copy the code
  • gin@8082
$ curl "localhost:8082/v1/hello? name=rk-dev" {"message":"Hello rk-dev"} # RPC log from server side -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- endTime = 2022-01-03 T19: sons. 23983 + 08:00 StartTime = 2022-01-03 T19: the sons. 239805 + 08:00 elapsedNano = 25460 timezone = CST ids={"eventId":"0d284016-f714-4c85-8af8-9715dc9ed35f"} app={"appName":"rk","appVersion":"","entryName":"gin","entryType":"GinEntry"} Env = {" arch ", "amd64", "az" : "*", "domain" : "*", "hostname" : "lark. Local", "localIP" : "10.8.0.2", "OS" : "Darwin", "realm" : "*", "region ":" * "} Payloads = {" apiMethod ":" GET ", "apiPath" : "/ v1 / hello," "apiProtocol" : "HTTP / 1.1", "apiQuery" : "name = fairly rk - dev", "userAgent" : "curl / 7. 64.1"} error={} counters={} pairs={} timing={} remoteAddr=localhost:54102 operation=/v1/hello resCode=200 eventStatus=Ended EOECopy the code
  • echo@8083
$ curl "localhost:8082/v1/hello? name=rk-dev" {"message":"Hello rk-dev"} # RPC log from server side -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- endTime = 2022-01-03 T19:19:11. 109838 + 08:00 StartTime = 2022-01-03 T19:19:11. 109817 + 08:00 elapsedNano = 21242 timezone = CST ids={"eventId":"34419c7c-1a78-484f-ba7a-bfca69178b82"} app={"appName":"rk","appVersion":"","entryName":"echo","entryType":"EchoEntry"} Env = {" arch ", "amd64", "az" : "*", "domain" : "*", "hostname" : "lark. Local", "localIP" : "10.8.0.2", "OS" : "Darwin", "realm" : "*", "region ":" * "} Payloads = {" apiMethod ":" GET ", "apiPath" : "/ v1 / hello," "apiProtocol" : "HTTP / 1.1", "apiQuery" : "name = fairly rk - dev", "userAgent" : "curl / 7. 64.1"} error={} counters={} pairs={} timing={} remoteAddr=localhost:56995 operation=/v1/hello resCode=200 eventStatus=Ended EOECopy the code
  • gf@8084
$ curl "localhost:8084/v1/hello? name=rk-dev" {"message":"Hello rk-dev"} # RPC log from server side -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- endTime = 2022-01-03 T19: this was. 905883 + 08:00 StartTime = 2022-01-03 T19: this was. 905858 + 08:00 elapsedNano = 24703 timezone = CST ids={"eventId":"58bf8706-09ff-434e-b405-d6cdb8dbe8c2"} app={"appName":"rk","appVersion":"","entryName":"gf","entryType":"GfEntry"} Env = {" arch ", "amd64", "az" : "*", "domain" : "*", "hostname" : "lark. Local", "localIP" : "10.8.0.2", "OS" : "Darwin", "realm" : "*", "region ":" * "} Payloads = {" apiMethod ":" GET ", "apiPath" : "/ v1 / hello," "apiProtocol" : "HTTP / 1.1", "apiQuery" : "name = fairly rk - dev", "userAgent" : "curl / 7. 64.1"} error={} counters={} pairs={} timing={} remoteAddr=localhost:58802 operation=/v1/hello resCode=200 eventStatus=Ended EOECopy the code
  • fiber@8085
$ curl "localhost:8085/v1/hello? name=rk-dev" {"message":"Hello rk-dev"} # RPC log from server side -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- endTime = 2022-01-03 T19: all the 834567 + 08:00 StartTime = 2022-01-03 T19: all the 834425 + 08:00 elapsedNano = 142332 timezone = CST ids={"eventId":"a98a6e9f-6519-4ded-971e-0b6e59f66096"} app={"appName":"rk","appVersion":"","entryName":"fiber","entryType":"FiberEntry"} Env = {" arch ", "amd64", "az" : "*", "domain" : "*", "hostname" : "lark. Local", "localIP" : "10.8.0.2", "OS" : "Darwin", "realm" : "*", "region ":" * "} Payloads = {" apiMethod ":" GET ", "apiPath" : "/ v1 / hello," "apiProtocol" : "HTTP", "apiQuery" : "name = fairly rk - dev", "userAgent" : "curl / 7.64.1 "} error={} counters={} pairs={} timing={} remoteAddr=127.0.0.1:63237 operation=/v1/hello resCode=200 eventStatus=Ended EOECopy the code
  • zero@8086
$ curl "localhost:8086/v1/hello? name=rk-dev" {"message":"Hello rk-dev"} # RPC log from server side -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- endTime = 2022-01-03 T19: mark. 835415 + 08:00 StartTime = 2022-01-03 T19: mark. 835391 + 08:00 elapsedNano = 24495 timezone = CST ids={"eventId":"a6a53d21-4cf4-4b45-97ca-2b190e438e9c","traceId":"bf7a2359d0813de4388dd11c4f161321"} app={"appName":"rk","appVersion":"","entryName":"zero","entryType":"ZeroEntry"} Env = {" arch ", "amd64", "az" : "*", "domain" : "*", "hostname" : "lark. Local", "localIP" : "10.8.0.2", "OS" : "Darwin", "realm" : "*", "region ":" * "} Payloads = {" apiMethod ":" GET ", "apiPath" : "/ v1 / hello," "apiProtocol" : "HTTP / 1.1", "apiQuery" : "name = fairly rk - dev", "userAgent" : "curl / 7. 64.1"} error={} counters={} pairs={} timing={} remoteAddr=localhost:65299 operation=/v1/hello resCode=200 eventStatus=Ended EOECopy the code
  • mux@8087
$ curl "localhost:8086/v1/hello? name=rk-dev" {"message":"Hello rk-dev"} # RPC log from server side -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- endTime = 2022-01-03 T19: then. 13191 + 08:00 StartTime = 2022-01-03 T19: then. 131889 + 08:00 elapsedNano = 21449 timezone = CST ids={"eventId":"8a0f2db6-8e13-4773-bedd-962060adbe41"} app={"appName":"rk","appVersion":"","entryName":"mux","entryType":"MuxEntry"} Env = {" arch ", "amd64", "az" : "*", "domain" : "*", "hostname" : "lark. Local", "localIP" : "10.8.0.2", "OS" : "Darwin", "realm" : "*", "region ":" * "} Payloads = {" apiMethod ":" GET ", "apiPath" : "/ v1 / hello," "apiProtocol" : "HTTP / 1.1", "apiQuery" : "name = fairly rk - dev", "userAgent" : "curl / 7. 64.1"} error={} counters={} pairs={} timing={} remoteAddr=127.0.0.1:52277 operation=/v1/hello resCode=200 eventStatus=Ended EOECopy the code

Fairly rk – the boot is introduced

Rk-boot is a framework for starting a variety of Web services through YAML. It’s kind of like Spring Boot. By integrating the RK-XXX family of libraries, you can launch a variety of Web frameworks. Of course, users can also customize the RK-XXX library to integrate into the RK-boot.

Fairly rk – highlight the boot

  • Start different Web frameworks with YAML files in the same format.
  • Even with different frameworks, the format of logging, Metrics, Tracing, etc
  • Users can customize YAML files by implementing rkentry.entry.

Web framework supported by RK-boot

Welcome to contribute the new Web framework to the RK-Boot series.

referencedocs & rk-ginAs an example.

The framework The development status The installation Rely on
Gin Stable go get github.com/rookie-ninja/rk-boot/gin rk-gin
gRPC Stable go get github.com/rookie-ninja/rk-boot/grpc rk-grpc
Echo Stable go get github.com/rookie-ninja/rk-boot/echo rk-echo
GoFrame Stable go get github.com/rookie-ninja/rk-boot/gf rk-gf
Fiber Testing go get github.com/rookie-ninja/rk-boot/fiber rk-fiber
go-zero Testing go get github.com/rookie-ninja/rk-boot/zero rk-zero
GorillaMux Testing go get github.com/rookie-ninja/rk-boot/mux rk-mux