Awesome Open Source
Awesome Open Source

Introduce

这是一个基于gin搭建的一个包含gorm, goredis,rabbitmq,websocket等操作相关操作的项目结构。

主要提供一些库和组件的实现案例,以及项目开发部署,发布,执行等流程。纯属个人兴趣,学习整理过程,

如有发现不合理的地方希望大家可以提出建议和指正。

通过执行 go get -u github.com/xiaobopang/go_init 来下载安装该项目,使用 govendor sync来拉取依赖到vendor目录,

注意vendor所在的目录一定要在第一个GOPAHT下。

通过 go build -o go_init main.go 来生成执行文件,其他平台编译方式见文档底部。

压缩go build的二进制文件,可使用 go build -ldflags "-s -w" -o go_init main.go

这里的 -ldflags 参数最终会在 go tool link 的时候传给它, go tool link -h 解释如下

    ...
    -s    disable symbol table
    -w    disable DWARF generation

这样处理可以删除掉调试符号,从而显著减小了文件大小(平均20%),也可以相对的隐藏一些源码信息。

如果你觉得这样压缩之后文件还是比较大,那么我们还可以再加一个UPX壳,这样编译过后的二进制文件

还可以压缩到原文件大小的五分之一。具体操作如下:

UPX安装 👈点击

    1、go build -ldflags "-s -w" -o go_init main.go

    2、upx go_init

    结果如下:

执行结果

启动服务:./run.sh start

停止服务:./run.sh stop

注意:有可能出现没有执行权限的情况,执行 sudo chmod +x run.sh来解决

1. Mysql

2. Redis

3. Websocket

4. RabbitMQ

5. ElasticSearch

Router 示例

        package router

        /*
        * @Script: routers.go
        * @Author: pangxiaobo
        * @Email: [email protected]
        * @Create At: 2018-11-27 18:19:27
        * @Last Modified By: pangxiaobo
        * @Last Modified At: 2018-12-12 14:25:18
        * @Description: This is description.
        */

        import (
                "net/http"

                "github.com/gin-gonic/gin"
                "github.com/xiaobopang/go_init/controller"
                "github.com/xiaobopang/go_init/middleware"
        )

        var indexCtl = new(controller.IndexController)
        var testCtl = new(controller.TestController)
        var wsCtl = new(controller.WsController)
        var mqCtl = new(controller.MqController)

        func SetupRouter() *gin.Engine {
                router := gin.Default()
                router.Use(gin.Recovery())
                //router.Use(gin.Logger())

                router.GET("/", indexCtl.Welcome)
                router.NoRoute(indexCtl.Handle404)

                // 简单的路由组: v1
                v1 := router.Group("/v1")
                {
                        v1.GET("/redis", testCtl.RedisTest) //redis 测试

                        v1.POST("/exchange", func(c *gin.Context) {
                                mqCtl.ExchangeHandler(c.Writer, c.Request)
                        })
                        v1.POST("/queue/bind", func(c *gin.Context) {
                                mqCtl.QueueBindHandler(c.Writer, c.Request)
                        })
                        v1.GET("/queue", func(c *gin.Context) {
                                mqCtl.QueueHandler(c.Writer, c.Request)
                        }) //consume queue
                        v1.POST("/queue", func(c *gin.Context) {
                                mqCtl.QueueHandler(c.Writer, c.Request)
                        }) //declare queue
                        v1.DELETE("/queue", func(c *gin.Context) {
                                mqCtl.QueueHandler(c.Writer, c.Request)
                        }) //delete queue
                        v1.POST("/publish", func(c *gin.Context) {
                                mqCtl.PublishHandler(c.Writer, c.Request)
                        })
                        v1.GET("/ws", func(c *gin.Context) {
                                wsCtl.WsHandler(c.Writer, c.Request)
                        })

                        v1.GET("/get_token", testCtl.GetToken)
                }

                router.GET("/redirect", func(c *gin.Context) {
                        c.Redirect(http.StatusMovedPermanently, "https://www.unclepang.com/")
                })

                v2 := router.Group("/v2")
                v2.Use(middleware.CORS(middleware.CORSOptions{}))
                {
                        v2.GET("/user", testCtl.GetUser)
                        v2.GET("/es", testCtl.ES)
                        v2.POST("/user", testCtl.AddUser)
                        v2.DELETE("/user", testCtl.DelUser)
                        v2.PATCH("/user", testCtl.UptUser)
                }

                return router
        }


Request and Response 示例

        package controller

        /*
        * @Script: test.go
        * @Author: pangxiaobo
        * @Email: [email protected]
        * @Create At: 2018-11-06 14:50:15
        * @Last Modified By: pangxiaobo
        * @Last Modified At: 2018-12-12 14:25:46
        * @Description: This is description.
        */

        import (
                "encoding/json"
                "fmt"
                "strconv"
                "time"

                "github.com/elastic/go-elasticsearch"
                "github.com/gin-gonic/gin"
                "github.com/xiaobopang/go_init/helper"
                "github.com/xiaobopang/go_init/lib"
                "github.com/xiaobopang/go_init/model"
        )

        type TestController struct{}

        func (t *TestController) GetNick(c *gin.Context) {
                nickname := c.DefaultQuery("nick", "guest")
                c.JSON(200, gin.H{
                        "code":      200,
                        "data":      map[string]string{"nickname": nickname},
                        "msg":       "success",
                        "timestamp": time.Now().Unix(),
                })
        }

        //获取用户
        func (t *TestController) GetUser(c *gin.Context) {

                id, _ := strconv.Atoi(c.Query("id"))
                fmt.Println(id)

                res, _ := model.GetUserById(id)

                c.JSON(200, gin.H{
                        "code":      200,
                        "data":      res,
                        "msg":       "success",
                        "timestamp": time.Now().Unix(),
                })
        }

        //获取用户
        func (t *TestController) UserList(c *gin.Context) {
                keyword := c.Query("keyword")
                pageNo := c.GetInt("page_number")
                pageSize := c.GetInt("page_size")

                res := model.UsersList(pageNo, pageSize, "username = ?", keyword)

                c.JSON(200, gin.H{
                        "code":      200,
                        "data":      res,
                        "msg":       "success",
                        "timestamp": time.Now().Unix(),
                })
        }

        //新增用户
        func (t *TestController) AddUser(c *gin.Context) {

                name := c.PostForm("name")
                password := helper.Md5(c.PostForm("password"))
                age, _ := strconv.Atoi(c.DefaultPostForm("age", "20"))
                gender, _ := strconv.Atoi(c.DefaultPostForm("gender", "1"))
                email := c.PostForm("email")

                res := model.AddUser(name, password, age, gender, email)

                c.JSON(200, gin.H{
                        "code":      200,
                        "data":      res,
                        "msg":       "success",
                        "timestamp": time.Now().Unix(),
                })
        }

        //删除用户 (硬删除)
        func (t *TestController) DelUser(c *gin.Context) {

                id, _ := strconv.Atoi(c.Query("id"))
                fmt.Println(id)

                res := model.DelUser(id)

                c.JSON(200, gin.H{
                        "code":      200,
                        "data":      res,
                        "msg":       "success",
                        "timestamp": time.Now().Unix(),
                })
        }

        //更新
        func (t *TestController) UptUser(c *gin.Context) {

                id, _ := strconv.Atoi(c.PostForm("id"))
                data := make(map[string]interface{})

                data["username"] = c.PostForm("name")
                data["password"] = helper.Md5(c.PostForm("password"))
                data["age"], _ = strconv.Atoi(c.DefaultPostForm("age", "20"))
                data["gender"], _ = strconv.Atoi(c.DefaultPostForm("gender", "1"))
                data["email"] = c.PostForm("email")
                data["updated_at"] = time.Now().Unix()

                res := model.UptUser(id, data)

                c.JSON(200, gin.H{
                        "code":      200,
                        "data":      res,
                        "msg":       "success",
                        "timestamp": time.Now().Unix(),
                })
        }

        //Redis 测试
        func (t *TestController) RedisTest(c *gin.Context) {
                redisKey := c.Query("redisKey")

                userInfo, err := lib.GetKey(redisKey)
                if err != nil {
                        data := make(map[string]interface{})
                        data["username"] = "jack"
                        data["age"] = 22
                        data["gender"] = "man"
                        data["email"] = "[email protected]"
                        data["updated_at"] = time.Now().Unix()
                        userInfo, err := json.Marshal(data)
                        lib.SetKey(redisKey, userInfo, 3600)
                        if err != nil {
                                fmt.Println(err)
                        }
                }
                c.JSON(200, gin.H{
                        "code":      200,
                        "data":      userInfo,
                        "msg":       "success",
                        "timestamp": time.Now().Unix(),
                })
        }

        func (t *TestController) GetToken(c *gin.Context) {
                token, err := lib.GenerateToken(1, "[email protected]")
                if err != nil {
                        fmt.Println("err: ", err)
                }
                c.JSON(200, gin.H{
                        "code":      200,
                        "data":      token,
                        "msg":       "success",
                        "timestamp": time.Now().Unix(),
                })

        }

        // es 测试
        func (t *TestController) ES(c *gin.Context) {
                cfg := elasticsearch.Config{
                        Addresses: []string{
                                "http://127.0.0.1:9201",
                        },
                }
                es, err := elasticsearch.NewClient(cfg)
                if err != nil {
                        fmt.Println("elasticsearch has error: ", err)
                }
                // 1. Get cluster info
                //
                res, err := es.Info()
                if err != nil {
                        fmt.Println("Error getting response: %s", err)
                }
                c.JSON(200, gin.H{
                        "code":      200,
                        "data":      res,
                        "msg":       "success",
                        "timestamp": time.Now().Unix(),
                })
        }


model 示例

        package model

        import (
                "time"
        )

        type User struct {
                ID        int    `gorm:"primary_key" json:"id"`
                Username  string `json:"username"`
                Password  string `json:"password"`
                Age       int    `json:"age"`
                Email     string `json:"email"`
                Gender    int    `json:"gender"`
                CreatedAt int64  `json:"created_at"`
                UpdatedAt int64  `json:"updated_at"`
        }

        type Page struct {
                TotalCount int
                List       interface{}
        }

        //通过 args可以动态传递多个参数
        func UsersList(pageNo int, pageSize int, args ...interface{}) (page Page) {
                var users []User
                var userCount []User
                var count uint

                db := DB.Table("user")
                if len(args) >= 2 {
                        db = db.Where(args[0], args[1:]...)
                } else {
                        db = db.Where(args[0])
                }
                db.Select("id,username,age,email,gender,created_at").Limit(pageSize).Offset((pageNo - 1) * pageSize).Scan(&users)

                if pageNo == 1 {
                        db.Select("id,username,age,email,gender,created_at").Scan(&userCount).Count(&count)
                        TotalCount := count
                        page.TotalCount = int(TotalCount)
                } else {
                        TotalCount := len(users)
                        page.TotalCount = int(TotalCount)
                }
                page.List = users
                return page
        }
        func GetUserById(id int) *User {
                var user User
                DB.First(&user, "id = ?", id)
                return &user
        }

        func AddUser(name string, password string, age int, gender int, email string) error {
                user := User{
                        Username:  name,
                        Password:  password,
                        Age:       age,
                        Gender:    gender,
                        Email:     email,
                        CreatedAt: time.Now().Unix(),
                }
                if err := DB.Create(&user).Error; err != nil {
                        return err
                }
                return nil
        }

        func DelUser(id int) error {
                if err := DB.Where("id = ?", id).Delete(&User{}).Error; err != nil {
                        return err
                }

                return nil
        }

        func UptUser(id int, data interface{}) error {

                if err := DB.Model(&User{}).Where("id = ? AND is_deleted = ? ", id, 0).Updates(data).Error; err != nil {
                        return err
                }

                return nil
        }

websocket 示例

前端通过访问 ws://localhost:7777/ws 即可与服务端建立websocket连接
        package controller

        import (
                "errors"
                "fmt"
                "github.com/gorilla/websocket"
                "net/http"
                "sync"
                "time"
        )

        var wsUpgrader = websocket.Upgrader{
                ReadBufferSize:    4096,
                WriteBufferSize:   4096,
                EnableCompression: true,
                HandshakeTimeout:  5 * time.Second,
                // CheckOrigin: 处理跨域问题,线上环境慎用
                CheckOrigin: func(r *http.Request) bool {
                        return true
                },
        }

        // 客户端读写消息
        type wsMessage struct {
                messageType int
                data        []byte
        }
        type Wscontroller struct{}

        // 客户端连接
        type wsConnection struct {
                wsSocket *websocket.Conn // 底层websocket
                inChan   chan *wsMessage // 读队列
                outChan  chan *wsMessage // 写队列

                mutex     sync.Mutex // 避免重复关闭管道
                isClosed  bool
                closeChan chan byte // 关闭通知
        }

        func (wsConn *wsConnection) wsReadLoop() {
                for {
                        // 读一个message
                        msgType, data, err := wsConn.wsSocket.ReadMessage()
                        if err != nil {
                                goto error
                        }
                        req := &wsMessage{
                                msgType,
                                data,
                        }
                        // 放入请求队列
                        select {
                        case wsConn.inChan <- req:
                        case <-wsConn.closeChan:
                                goto closed
                        }
                }
        error:
                wsConn.wsClose()
        closed:
        }
        func (wsConn *wsConnection) wsWriteLoop() {
                for {
                        select {
                        // 取一个应答
                        case msg := <-wsConn.outChan:
                                // 写给websocket
                                if err := wsConn.wsSocket.WriteMessage(msg.messageType, msg.data); err != nil {
                                        goto error
                                }
                        case <-wsConn.closeChan:
                                goto closed
                        }
                }
        error:
                wsConn.wsClose()
        closed:
        }

        func (wsConn *wsConnection) procLoop() {
                // 启动一个gouroutine发送心跳
                go func() {
                        for {
                                time.Sleep(2 * time.Second)
                                if err := wsConn.wsWrite(websocket.TextMessage, []byte("heartbeat from server")); err != nil {
                                        fmt.Println("heartbeat fail")
                                        wsConn.wsClose()
                                        break
                                }
                        }
                }()

                // 这是一个同步处理模型(只是一个例子),如果希望并行处理可以每个请求一个gorutine,注意控制并发goroutine的数量!!!
                for {
                        msg, err := wsConn.wsRead()
                        if err != nil {
                                fmt.Println("read fail")
                                break
                        }
                        fmt.Println(string(msg.data))
                        err = wsConn.wsWrite(msg.messageType, msg.data)
                        if err != nil {
                                fmt.Println("write fail")
                                break
                        }
                }
        }

        func (w *Wscontroller) WsHandler(resp http.ResponseWriter, req *http.Request) {
                // 应答客户端告知升级连接为websocket
                wsSocket, err := wsUpgrader.Upgrade(resp, req, nil)
                if err != nil {
                        return
                }
                wsConn := &wsConnection{
                        wsSocket:  wsSocket,
                        inChan:    make(chan *wsMessage, 1000),
                        outChan:   make(chan *wsMessage, 1000),
                        closeChan: make(chan byte),
                        isClosed:  false,
                }

                // 处理器
                go wsConn.procLoop()
                // 读协程
                go wsConn.wsReadLoop()
                // 写协程
                go wsConn.wsWriteLoop()
        }

        func (wsConn *wsConnection) wsWrite(messageType int, data []byte) error {
                select {
                case wsConn.outChan <- &wsMessage{messageType, data}:
                case <-wsConn.closeChan:
                        return errors.New("websocket closed")
                }
                return nil
        }

        func (wsConn *wsConnection) wsRead() (*wsMessage, error) {
                select {
                case msg := <-wsConn.inChan:
                        return msg, nil
                case <-wsConn.closeChan:
                }
                return nil, errors.New("websocket closed")
        }

        func (wsConn *wsConnection) wsClose() {
                wsConn.wsSocket.Close()

                wsConn.mutex.Lock()
                defer wsConn.mutex.Unlock()
                if !wsConn.isClosed {
                        wsConn.isClosed = true
                        close(wsConn.closeChan)
                }
        }

RabbitMQ 示例

        package controller

        import (
                "encoding/json"
                "flag"
                "fmt"
                "io/ioutil"
                "log"
                "net/http"

                "github.com/streadway/amqp"
        )

        var (
                amqpUri = flag.String("amqp", "amqp://guest:[email protected]:5672/", "amqp uri")
        )

        func init() {
                flag.Parse()
        }

        type MqController struct{}

        // Entity for HTTP Request Body: Message/Exchange/Queue/QueueBind JSON Input
        type MessageEntity struct {
                Exchange     string `json:"exchange"`
                Key          string `json:"key"`
                DeliveryMode uint8  `json:"deliverymode"`
                Priority     uint8  `json:"priority"`
                Body         string `json:"body"`
        }

        type ExchangeEntity struct {
                Name       string `json:"name"`
                Type       string `json:"type"`
                Durable    bool   `json:"durable"`
                AutoDelete bool   `json:"autodelete"`
                NoWait     bool   `json:"nowait"`
        }

        type QueueEntity struct {
                Name       string `json:"name"`
                Durable    bool   `json:"durable"`
                AutoDelete bool   `json:"autodelete"`
                Exclusive  bool   `json:"exclusive"`
                NoWait     bool   `json:"nowait"`
        }

        type QueueBindEntity struct {
                Queue    string   `json:"queue"`
                Exchange string   `json:"exchange"`
                NoWait   bool     `json:"nowait"`
                Keys     []string `json:"keys"` // bind/routing keys
        }

        // RabbitMQ Operate Wrapper
        type RabbitMQ struct {
                conn    *amqp.Connection
                channel *amqp.Channel
                done    chan error
        }

        func (r *RabbitMQ) Connect() (err error) {
                r.conn, err = amqp.Dial(*amqpUri)
                if err != nil {
                        log.Printf("[amqp] connect error: %s\n", err)
                        return err
                }
                r.channel, err = r.conn.Channel()
                if err != nil {
                        log.Printf("[amqp] get channel error: %s\n", err)
                        return err
                }
                r.done = make(chan error)
                return nil
        }

        func (r *RabbitMQ) Publish(exchange, key string, deliverymode, priority uint8, body string) (err error) {
                err = r.channel.Publish(exchange, key, false, false,
                        amqp.Publishing{
                                Headers:         amqp.Table{},
                                ContentType:     "text/plain",
                                ContentEncoding: "",
                                DeliveryMode:    deliverymode,
                                Priority:        priority,
                                Body:            []byte(body),
                        },
                )
                if err != nil {
                        log.Printf("[amqp] publish message error: %s\n", err)
                        return err
                }
                return nil
        }

        func (r *RabbitMQ) DeclareExchange(name, typ string, durable, autodelete, nowait bool) (err error) {
                err = r.channel.ExchangeDeclare(name, typ, durable, autodelete, false, nowait, nil)
                if err != nil {
                        log.Printf("[amqp] declare exchange error: %s\n", err)
                        return err
                }
                return nil
        }

        func (r *RabbitMQ) DeleteExchange(name string) (err error) {
                err = r.channel.ExchangeDelete(name, false, false)
                if err != nil {
                        log.Printf("[amqp] delete exchange error: %s\n", err)
                        return err
                }
                return nil
        }

        func (r *RabbitMQ) DeclareQueue(name string, durable, autodelete, exclusive, nowait bool) (err error) {
                _, err = r.channel.QueueDeclare(name, durable, autodelete, exclusive, nowait, nil)
                if err != nil {
                        log.Printf("[amqp] declare queue error: %s\n", err)
                        return err
                }
                return nil
        }

        func (r *RabbitMQ) DeleteQueue(name string) (err error) {
                // TODO: other property wrapper
                _, err = r.channel.QueueDelete(name, false, false, false)
                if err != nil {
                        log.Printf("[amqp] delete queue error: %s\n", err)
                        return err
                }
                return nil
        }

        func (r *RabbitMQ) BindQueue(queue, exchange string, keys []string, nowait bool) (err error) {
                for _, key := range keys {
                        if err = r.channel.QueueBind(queue, key, exchange, nowait, nil); err != nil {
                                log.Printf("[amqp] bind queue error: %s\n", err)
                                return err
                        }
                }
                return nil
        }

        func (r *RabbitMQ) UnBindQueue(queue, exchange string, keys []string) (err error) {
                for _, key := range keys {
                        if err = r.channel.QueueUnbind(queue, key, exchange, nil); err != nil {
                                log.Printf("[amqp] unbind queue error: %s\n", err)
                                return err
                        }
                }
                return nil
        }

        func (r *RabbitMQ) ConsumeQueue(queue string, message chan []byte) (err error) {
                deliveries, err := r.channel.Consume(queue, "", true, false, false, false, nil)
                if err != nil {
                        log.Printf("[amqp] consume queue error: %s\n", err)
                        return err
                }
                go func(deliveries <-chan amqp.Delivery, done chan error, message chan []byte) {
                        for d := range deliveries {
                                message <- d.Body
                        }
                        done <- nil
                }(deliveries, r.done, message)
                return nil
        }

        func (r *RabbitMQ) Close() (err error) {
                err = r.conn.Close()
                if err != nil {
                        log.Printf("[amqp] close error: %s\n", err)
                        return err
                }
                return nil
        }

        // HTTP Handlers
        func (m *MqController) QueueHandler(w http.ResponseWriter, r *http.Request) {
                if r.Method == "POST" || r.Method == "DELETE" {
                        if r.Body == nil {
                                fmt.Println("missing form body")
                                return
                        }

                        body, err := ioutil.ReadAll(r.Body)
                        if err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }

                        entity := new(QueueEntity)
                        if err = json.Unmarshal(body, entity); err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }

                        rabbit := new(RabbitMQ)
                        if err = rabbit.Connect(); err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }
                        defer rabbit.Close()

                        if r.Method == "POST" {
                                if err = rabbit.DeclareQueue(entity.Name, entity.Durable, entity.AutoDelete, entity.Exclusive, entity.NoWait); err != nil {
                                        http.Error(w, err.Error(), http.StatusInternalServerError)
                                        return
                                }
                                w.Write([]byte("declare queue ok"))
                        } else if r.Method == "DELETE" {
                                if err = rabbit.DeleteQueue(entity.Name); err != nil {
                                        http.Error(w, err.Error(), http.StatusInternalServerError)
                                        return
                                }
                                w.Write([]byte("delete queue ok"))
                        }
                } else if r.Method == "GET" {
                        r.ParseForm()
                        rabbit := new(RabbitMQ)
                        if err := rabbit.Connect(); err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }
                        defer rabbit.Close()

                        message := make(chan []byte)

                        for _, name := range r.Form["name"] {
                                if err := rabbit.ConsumeQueue(name, message); err != nil {
                                        fmt.Println("Receive message ", message)
                                        http.Error(w, err.Error(), http.StatusInternalServerError)
                                        return
                                }
                        }

                        w.Write([]byte(""))
                        w.(http.Flusher).Flush()

                        for {
                                fmt.Fprintf(w, "%s\n", <-message)
                                w.(http.Flusher).Flush()
                        }
                } else {
                        w.WriteHeader(http.StatusMethodNotAllowed)
                }
        }

        func (m *MqController) QueueBindHandler(w http.ResponseWriter, r *http.Request) {
                if r.Method == "POST" || r.Method == "DELETE" {
                        body, err := ioutil.ReadAll(r.Body)
                        if err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }

                        entity := new(QueueBindEntity)
                        if err = json.Unmarshal(body, entity); err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }

                        rabbit := new(RabbitMQ)
                        if err = rabbit.Connect(); err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }
                        defer rabbit.Close()

                        if r.Method == "POST" {
                                if err = rabbit.BindQueue(entity.Queue, entity.Exchange, entity.Keys, entity.NoWait); err != nil {
                                        http.Error(w, err.Error(), http.StatusInternalServerError)
                                        return
                                }
                                w.Write([]byte("bind queue ok"))
                        } else if r.Method == "DELETE" {
                                if err = rabbit.UnBindQueue(entity.Queue, entity.Exchange, entity.Keys); err != nil {
                                        http.Error(w, err.Error(), http.StatusInternalServerError)
                                        return
                                }
                                w.Write([]byte("unbind queue ok"))
                        }
                } else {
                        w.WriteHeader(http.StatusMethodNotAllowed)
                }
        }

        func (m *MqController) PublishHandler(w http.ResponseWriter, r *http.Request) {
                if r.Method == "POST" {
                        body, err := ioutil.ReadAll(r.Body)
                        if err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }

                        entity := new(MessageEntity)
                        if err = json.Unmarshal(body, entity); err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }

                        rabbit := new(RabbitMQ)
                        if err = rabbit.Connect(); err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }
                        defer rabbit.Close()

                        if err = rabbit.Publish(entity.Exchange, entity.Key, entity.DeliveryMode, entity.Priority, entity.Body); err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }
                        w.Write([]byte("publish message ok"))
                } else {
                        w.WriteHeader(http.StatusMethodNotAllowed)
                }
        }

        func (m *MqController) ExchangeHandler(w http.ResponseWriter, r *http.Request) {
                if r.Method == "POST" || r.Method == "DELETE" {
                        body, err := ioutil.ReadAll(r.Body)
                        if err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }

                        entity := new(ExchangeEntity)
                        if err = json.Unmarshal(body, entity); err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }

                        rabbit := new(RabbitMQ)
                        if err = rabbit.Connect(); err != nil {
                                http.Error(w, err.Error(), http.StatusInternalServerError)
                                return
                        }
                        defer rabbit.Close()

                        if r.Method == "POST" {
                                if err = rabbit.DeclareExchange(entity.Name, entity.Type, entity.Durable, entity.AutoDelete, entity.NoWait); err != nil {
                                        http.Error(w, err.Error(), http.StatusInternalServerError)
                                        return
                                }
                                w.Write([]byte("declare exchange ok"))
                        } else if r.Method == "DELETE" {
                                if err = rabbit.DeleteExchange(entity.Name); err != nil {
                                        http.Error(w, err.Error(), http.StatusInternalServerError)
                                        return
                                }
                                w.Write([]byte("delete exchange ok"))
                        }
                } else {
                        w.WriteHeader(http.StatusMethodNotAllowed)
                }
        }

声明queue,注意:你的request格式必须是 Content-Type:application/json

    http://127.0.0.1:7777/queue POST

    {
            "name":"test",
            "durable":false,
            "autodelete":true,
            "exclusive":false,
            "nowait":false
    }

声明exchange,注意:你的request格式必须是 Content-Type:application/json

    http://127.0.0.1:7777/exchange POST

   {
            "name":"test",
            "type":"direct",
            "durable":false,
            "autodelete":true,
            "nowait":false
    }

绑定queue,注意:你的request格式必须是 Content-Type:application/json

    http://127.0.0.1:7777/queue/bind POST

    {
            "queue":"test",
            "exchange":"test",
            "nowait":false,
            "keys": ["router"]
    }

pusblish messge,注意:你的request格式必须是 Content-Type:application/json

    http://127.0.0.1:7777/publish POST

    {
            "exchange":"test",
            "key":"router",
            "deliverymode":2,  //1:不用持久化,2:消息持久化
            "priority":3,  //优先级 (一般情况下1-10之间)
            "body":"this is a message from test."
    }

消费queue

    http://127.0.0.1:7777/queue?name=test   GET

如果你使用的是MacOS,那么Mac下编译Linux, Windows平台的64位可执行程序如下:

编译Linux服务器可执行文件:

    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o go_init main.go

编译Windows服务器可执行文件:

    CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o go_init main.go

如果你使用的是Linux系统,那么Linux下编译Mac, Windows平台的64位可执行程序如下:

编译MacOS可执行文件:

    CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o go_init main.go

编译windows下可执行文件:

    CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o go_init main.go

如果你使用的是Windows系统,那么Windows下编译Mac, Linux平台的64位可执行程序如下:

编译MacOS可执行文件如下:

    SET CGO_ENABLED=0

    SET GOOS=darwin

    SET GOARCH=amd64

    go build -o go_init main.go

编译Windows可执行文件如下:

    SET CGO_ENABLED=0

    SET GOOS=linux

    SET GOARCH=amd64

    go build -o go_init main.go

Nginx负载均衡


        user nginx;
        worker_processes auto;
        error_log /var/log/nginx/error.log;
        pid /var/run/nginx.pid;

        events {
        worker_connections 1024;
        }

        http {
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
        
        access_log  /var/log/nginx/access.log  main;
        
        sendfile            on;
        tcp_nopush          on;
        tcp_nodelay         on;
        keepalive_timeout   65;
        types_hash_max_size 2048;
        
        include             /etc/nginx/mime.types;
        default_type        application/octet-stream;
                
        index   index.html index.htm;
        
        upstream docker_nginx {
                ip_hash; #同一个ip一定时间内负载到一台机器
                server 172.31.0.155:8081;
                server 172.31.0.155:8082;
                server 172.31.0.155:8083;
                server 172.31.0.155:8084;
        }
        
        server {
                # 使用openssl自建的rsa证书
                ssl_certificate /opt/ssl/nginx.unclepang.com.crt;
                ssl_certificate_key /opt/ssl/nginx.unclepang.com.key;
                ssl_session_timeout 5m;
                ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
                ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
                ssl_prefer_server_ciphers on;
        
                listen 443;
                ssl on;
                server_name www.unclepang.com;
                
                location / {
                        # 代理到真实机器,如果真实机器也安装了https则使用https
                        # 一般代理集群对流量进行了https后,真实机器可不再使用https
                        proxy_pass http://docker_nginx;
                }
        }
        }


Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
Go (198,701
Json (11,381
Websocket (5,452
Rabbitmq (2,154
Gin (729
Gorm (453
Iris (215
Go Redis (29
Related Projects