基於Gin框架的網關設計開發


  年尾這幾天自己研究並開發了一個基於Go語言的網關項目設計開發,並對其進行了開源,需要的小伙伴請點擊:【Github地址】自主下載使用,README 中有還算詳細的說明文檔,本人不喜歡前端,所以也沒有去找一個開源的后台頁面接入,但提供了相應的數據添加接口,接口地址在項目【DOC】中說明,表結構設計也在【TABLE】中有非常詳細的說明。

  另外本人還有另一個工具覺得很方便大家:【請求重新提交

使用注意

  1. 項目依賴都是必須的,其配置存放於【conf】配置中心
  2. 需要根據 TABLE 嚴格按照說明對MongoDB的數據結構和數據進行控制,否則不能正常使用
  3. 看完覺得不錯,必須✨✨✨✨哦

項目依賴

  1. Gin 框架 
  2. Redis
  3. MongoDB

主要實現功能

  1. 路由轉發,包括超時設置(基礎功能 GET / POST)
  2. 多 IP / 域名 配置
  3. 路由 dns (只支持輪訓)
  4. 請求限流
  5. 數據緩存
  6. 請求容錯
  7. 統一鑒權

設計目標

  1. 模塊化
  2. 配置化

 

入口:main 函數,為了方便后續的擴展,所以什么也不放

 

package main

import (
	"gw/route"
)

// main 函數沒什么好說的,盡量干凈,方便后續的模塊添加
func main() {
	r := route.Route()
	r.Run(":1323")
}

 路由:路由采取了分隔,將前后端的路由分開

package route

import (
	"gw/route/admin"
	"gw/route/api"

	"github.com/gin-gonic/gin"
)

// 調用設置路由
func Route() *gin.Engine {
	r := gin.Default()
	//外部調用路由
	api.Route(r)

	//后台接口調用路由
	admin.Route(r)

	return r
}

 后台接口:提供了添加 group 和 wg 表的基本接口,讓項目能跑起來

package admin

import (
	"gw/pkg/admin"

	"github.com/gin-gonic/gin"
)

func Route(r *gin.Engine) {
        // 路由訪問轉發的接口      
	r.POST("/req/add/api", admin.Add)

        // api 動態生成轉發接口的表添加
	r.POST("/req/add/group", admin.AddGroup)
}

 前台接口:動態循環路由組(group),將其配置添加到模糊路由中,為了解決后續增加 wg 表的配置需要重啟

package api

import (
	"fmt"

	"gw/pkg/api"
	"gw/library"
	"gw/pkg/middle"

	"github.com/gin-gonic/gin"
)

func Route(r *gin.Engine) {
	list, err := library.Group("group")
	if err != nil {
		panic(fmt.Sprintf("Api Route Was Wrong Err Was %s", err))
	}

	//動態加載路由,根據mongoDB中的path加載
	for _, v := range list {
		pth := v.Group
		r.Any(fmt.Sprintf("%s%s", pth, "*action"), api.Run, middle.Body())
	}
}

 執行程序入口:該入口是整個系統的邏輯入口,目前還沒想到更好的方式

package api

import (
	"fmt"
	"net/http"
	"time"

	"gw/conf"
	"gw/library"
	"gw/pkg/ds"
	"gw/pkg/dy"
	"gw/pkg/fw"
	"gw/util"

	"github.com/gin-gonic/gin"
)

// 入口函數
func Run(c *gin.Context) {
	t := time.NewTimer(conf.RequestTimeOut * time.Second)
	//設置 global
	var glb G
	glb.Rch = make(chan string)
	glb.Ech = make(chan error)

	go func(c *gin.Context, glb *G) {
		glb.RequestTime = util.GetTime()

		//設置請求訪問的數據
		if err := glb.SetInfo(c); err != nil {
			glb.Ech <- err
			return
		}

		//容錯
		decay := dy.Decay{
			Open:      glb.Md.Decay,
			DecayTime: glb.Md.DecayTime,
			Ctx:       c,
		}
		decayBody := decay.Start()
		if decayBody != "" {
			glb.Rch <- decayBody
			return
		}

		//獲取要訪問的url
		dns := ds.Dns{
			Ds:  glb.Md.Dns,
			Pth: glb.Md.To,
			Ctx: c,
		}
		dns.GetRestUrl()
		glb.To = dns.To
		glb.Query = dns.Query

		//流量檢查
		flow := fw.Flow{
			Path: glb.To,
			Num:  glb.Md.Flow,
		}
		if err := flow.Check(); err != nil {
			glb.Ech <- err
			return
		}

		//發起請求
		hp := library.HttpRequest{
			Method:    glb.Md.Method,
			To:        glb.To,
			Query:     glb.Query,
			Out:       glb.Md.Timeout,
			CacheTime: glb.Md.CacheTime,
		}

		//發起請求
		body, err := hp.Http()
		if err != nil {
			glb.Ech <- err
			return
		}

		//寫入上下文,目前用於容錯
		c.Set("RequestBody", body)

		glb.Rch <- body
	}(c, &glb)

	select {
	case rch := <-glb.Rch:
		c.String(http.StatusOK, rch)
	case ech := <-glb.Ech:
		c.String(http.StatusInternalServerError, fmt.Sprintln(ech))
	case <-t.C:
		c.String(http.StatusNotFound, "request time out")
	}

	t.Stop()
}

 

從上述代碼中可以看到大致的項目設計了,具體功能代碼不再單獨貼圖了,大家可以拿到代碼后看一下,項目設計的挺簡單的,很方便擴展


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM