动手搓一个kubernetes管理平台(3)-后端框架

这篇具有很好参考价值的文章主要介绍了动手搓一个kubernetes管理平台(3)-后端框架。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

后端框架的选择面比较大,由于不涉及复杂的调度/分布式管理等场景,所以后端选用一个标准的web server即可,比如gin, iris, beego等等,因为正好最近在看iris的一些项目,所以就选用了irsi+corba的框架进行后端开发 。

通过cobra进行初始化的操作就不在赘述,这边先show一下相关的目录结构

cmd # 启动命令
common # 通用组件,如mysql, conf, log等
conf # 配置表
core/server #  核心服务,http server
dao/v1 # 数据层
docs # 文档
http # 接口层
img # readme的截图,架构图
migrate # 首次启动的数据同步 
pkg # 非通用组件,如k8s客户端,websocket等
service/v1 # 业务逻辑的封装
structs/v1 # 所有结构体
main.go # 入口

封装KubeMgrServer的对象

package server

import (
	"fmt"
	"github.com/iris-contrib/swagger/v12"
	"github.com/iris-contrib/swagger/v12/swaggerFiles"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/context"
	"github.com/kataras/iris/v12/sessions"
	"github.com/kataras/iris/v12/sessions/sessiondb/redis"
	cfg "kubemgr/common/configparse"
	log "kubemgr/common/formatlog"
	"kubemgr/common/i18n"
	"kubemgr/common/mysql"
	redis_common "kubemgr/common/redis"
	_ "kubemgr/docs" // docs is generated by Swag CLI, you have to import it.
	"kubemgr/migrate"
	"strings"
	"time"
)

// session管理
const SessionCookieName = "KUBEMGR_SESS"

var SessionMgr *sessions.Sessions

type KubeMgrServer struct {
	app        *iris.Application
	rootRoute  iris.Party
	configPath string
	bind       string
}

var km *KubeMgrServer

// 注册redis
func NewRedis() *redis.Database {
	db := redis.New(redis.Config{
		Network:   "tcp",
		Addr:      cfg.GlobalConf.GetStr("common", "redisbind"),
		Timeout:   time.Duration(30) * time.Second,
		MaxActive: cfg.GlobalConf.GetInt("common", "redismaxactive"),
		Password:  cfg.GlobalConf.GetStr("common", "redispasswd"),
		Database:  cfg.GlobalConf.GetStr("common", "redisdb"),
		Prefix:    cfg.GlobalConf.GetStr("common", "redisprefix"),
		Driver:    redis.GoRedis(), // redis.Radix() can be used instead.
	})
	// defer db.Close()
	return db
}

// 启动服务
func Listen(route func(party iris.Party), confgPath string, serverBindHost string, serverBindPort int) error {
	bind := fmt.Sprintf("%v:%v", serverBindHost, serverBindPort)
	km = NewServer(confgPath, bind)
	route(km.rootRoute)
	return km.app.Run(iris.Addr(bind))
}

// 初始化服务对象
func NewServer(confgPath, bind string) *KubeMgrServer {
	c := &KubeMgrServer{}
	c.app = iris.New()
	c.configPath = confgPath
	c.bind = bind
	return c.bootstrap()
}

// 初始化KubeMgrServer对象,初始化各个模块
func (e *KubeMgrServer) bootstrap() *KubeMgrServer {
	e.setUpRootRoute()
	e.setUpConfig()
	e.setUpLogger()
	e.setUpDB()
	e.setUpSession()
	e.setResultHandler()
	e.setUpErrHandler()
	e.setDBInitial()
	return e
}

// 初始化路由,所有路由的/ 路径,均为kubemgr
func (e *KubeMgrServer) setUpRootRoute() {
	e.app.Any("/", func(ctx *context.Context) {
		ctx.Redirect("/kubemgr")
	})
	c := swagger.Config{
		URL: "/kubemgr/swagger/doc.json",
	}
	e.app.Get("/kubemgr/swagger/{any:path}", swagger.CustomWrapHandler(&c, swaggerFiles.Handler))
	e.rootRoute = e.app.Party("/kubemgr")
}

// 初始化配置文件
func (e *KubeMgrServer) setUpConfig() {
	cfg.GlobalConf.CfgInit(e.configPath)
}

// 初始化日志
func (e *KubeMgrServer) setUpLogger() {
	// logname := cfg.GlobalConf.GetStr("common", "logname")
	loglevel := cfg.GlobalConf.GetStr("common", "loglevel")
	log.InitLog(loglevel)
}

// 初始化DB
func (e *KubeMgrServer) setUpDB() {
	mysql.DB.InitConn()
	redis_common.DB.NewRds()
}

// 初始化session
func (e *KubeMgrServer) setUpSession() {
	SessionMgr = sessions.New(sessions.Config{Cookie: SessionCookieName, AllowReclaim: true, Expires: time.Duration(cfg.GlobalConf.GetInt("common", "sessiontimeout")) * time.Hour})
	db := NewRedis()
	SessionMgr.UseDatabase(db)
	e.rootRoute.Use(SessionMgr.Handler())
}

// 初始化数据库实例
func (e *KubeMgrServer) setDBInitial() {
	DataSourceUrl := fmt.Sprintf("%s%s%s", "mysql://", cfg.GlobalConf.GetStr("mysql", "datasource"), "?multiStatements=true")
	migrate.InitDB(DataSourceUrl, 5*time.Second)
}

// 初始化response
func (e *KubeMgrServer) setResultHandler() {
	e.rootRoute.Use(func(ctx *context.Context) {
		ctx.Next()
		if ctx.GetStatusCode() >= iris.StatusOK && ctx.GetStatusCode() < iris.StatusBadRequest {
			if ctx.Values().Get("token") != nil {
				_, _ = ctx.Write(ctx.Values().Get("token").([]uint8))
			} else {
				resp := iris.Map{
					"success": true,
					"data":    ctx.Values().Get("data"),
				}
				_ = ctx.JSON(resp)
			}
		}
	})
}

// 捕获异常返回
func (e *KubeMgrServer) setUpErrHandler() {
	e.rootRoute.OnAnyErrorCode(func(ctx iris.Context) {
		//如果报错message为空,且errcode为404,则进行错误返回
		if ctx.Values().GetString("message") == "" {
			switch ctx.GetStatusCode() {
			case iris.StatusNotFound:
				ctx.Values().Set("message", "the server could not find the requested resource")
			}
		}

		message := ctx.Values().Get("message")
		if message == nil || message == "" {
			message = ctx.Values().Get("iris.context.error")
		}
		// 默认接口返回错误信息为US
		lang := ctx.Values().GetString("language")
		if lang == "" {
			lang = i18n.LanguageEnUS
		}
		var (
			translateMessage string
			err              error
			originMessage    string
		)

		switch value := message.(type) {
		case string:
			originMessage = message.(string)
			translateMessage, err = i18n.Translate(lang, value)
		case []string:
			originMessage = strings.Join(value, ",")
			if len(value) > 0 {
				translateMessage, err = i18n.Translate(lang, value[0], value[1:])
			}
		case context.ErrPrivate:
			err := message.(context.ErrPrivate)
			translateMessage = err.Error()
		}
		msg := translateMessage
		if err != nil {
			e.app.Logger().Debug(err)
			msg = originMessage
		}
		er := iris.Map{
			"success": false,
			"code":    ctx.GetStatusCode(),
			"message": msg,
		}
		_ = ctx.JSON(er)
	})
}

上述代码对KubeMgrServer的对象进行了初步的初始化,封装了日志/DB/缓存的/异常/返回,在完整基本的封装以后,可以进行接口的封装了,iris或者gin之类的 框架,最大的优势在于有ctx的概念,可以在请求的上下文中进行数据的修改,提取,插入等等,这就很方便了,可以利用这点就行token的提取,参数的抓取 ,甚至于请求头的改写(比如将http请求升级到websocket)。

在完成基本主体的封装后,开始编写接口,首先将接口分个类, 分成对应功能的目录 :

http
├── api
│   └── v1
│       ├── audit
│       │   ├── audit.go
│       │   └── types.go
│       ├── cluster
│       │   ├── cluster.go
│       │   ├── clusterrole.go
│       │   ├── member.go
│       │   └── types.go
│       ├── kubernetes
│       │   ├── prometheus.go
│       │   ├── proxy.go
│       │   └── types.go
│       ├── role
│       │   ├── role.go
│       │   └── types.go
│       ├── session
│       │   ├── session.go
│       │   └── types.go
│       ├── user
│       │   ├── types.go
│       │   └── user.go
│       ├── v1.go
│       └── ws
│           └── ws.go
└── route
    └── route.go

上述目录将不同功能的接口基于不同目录进行了封装,类似如下代码:

package audit

import (
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/context"
	log "kubemgr/common/formatlog"
	v1AuditService "kubemgr/service/v1/audit"
)

type Handler struct {
	auditService v1AuditService.Service
}

func NewHandler() *Handler {
	return &Handler{
		auditService: v1AuditService.NewService(),
	}
}

func (h *Handler) ListPlatFormAuditRecord() iris.Handler {
	return func(ctx *context.Context) {
		pageNum := ctx.URLParamIntDefault("pageNum", 0)
		pageSize := ctx.URLParamIntDefault("pageSize", 10)
		fromTime := ctx.URLParam("fromTime")
		endTime := ctx.URLParam("toTime")
		total, auditLogs, err := h.auditService.ListPlatFormAuditRecord(pageNum, pageSize, fromTime, endTime)
		if err != nil {
			log.Errorf("获取审计日志失败: %v", err.Error())
			ctx.StatusCode(iris.StatusInternalServerError)
			ctx.Values().Set("message", err.Error())
			return
		}

		var allAuditLogs ListAuditLogs
		allAuditLogs.Total = total
		allAuditLogs.AuditLogs = auditLogs

		ctx.StatusCode(iris.StatusOK)
		ctx.Values().Set("data", &allAuditLogs)
	}
}

func Install(parent iris.Party) {
	handler := NewHandler()
	sp := parent.Party("/audit")
	sp.Get("/list", handler.ListPlatFormAuditRecord())
}

然后在v1.go里面,将每个目录的接口接入root_route,并进行基础功能的封装,如日志,认证等等

func AddV1Route(app iris.Party) {
	v1Party := app.Party("/v1")
	session.Install(v1Party)

  // 接口国际化,基于profile内的语言标识,来返回中文/英文
	v1Party.Use(langHandler())
  // websocket请求,将http请求升级到websocket,由于websocket获取token的方式比较特殊,所以不放入统一认证的方法,单独编写
	wss.Install(v1Party)

	// 基础路由的首次封装,添加认证,权限,角色的相关解析操作
	authParty := v1Party.Party("")
	authParty.Use(authHandler())
	authParty.Use(resourceExtractHandler())
	authParty.Use(roleHandler())

	// 将封装好的路由导入平台用户/角色权限管理的相关接口
	user.Install(authParty)
	role.Install(authParty)

	// 将封装好的路由导入平台审计/集群管理的相关接口
	audit.Install(authParty)
	cluster.Install(authParty)
	kubernetes.Install(authParty)
}

至此,可以基于上面的代码看到api的请求路径

请求→v1.go(进行路由封装和分发)→分发到的明细路由处理(例如audit.go)→转发到业务实际处理逻辑,比如调用k8或者crud等

大致上的后端逻辑就是上面这样了,平台的基本操作用不到pkg,简单的crud即可。这个和其他运维或者中台管理的逻辑大致上没什么区别,主要后面要看对于k8s的操作。

个人公众号, 分享一些日常开发,运维工作中的日常以及一些学习感悟,欢迎大家互相学习,交流

动手搓一个kubernetes管理平台(3)-后端框架,从零开始写一个k8s管理平台,kubernetes,容器,云原生文章来源地址https://www.toymoban.com/news/detail-809818.html

到了这里,关于动手搓一个kubernetes管理平台(3)-后端框架的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Kubernetes部署+kubesphere管理平台安装

    Kubernetes官网;kubesphere官网           不论是Kubernetes官网还是找的其它部署步骤,基本都是推荐搭建集群的方式,是为了实现高可用.....等等,这样一来至少需要两台或三台的服务器来搭建,这样对我们的成本也是非常大的,所以我就尝试了用一台机器来部署,下面是具体

    2024年02月15日
    浏览(36)
  • 实战篇:从零开始构建一个完整的校园一卡通平台

    ✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 | SpringBoot/SSM Python实战项目 | Django 微信小

    2024年01月20日
    浏览(93)
  • 开发那点事(十六)从零开始搭建一个NFT数字藏品平台

    写在前面的话 从6月初到七月研究了将近一个月NFT 区块链这方面的东西,从啥都不会到了解原理,总算是有点成果了,在这里分享给大家。 核心大纲 百度超级链开放网络(Solidity语言) 集成openzeppelin中的ERC721合约快速完成合约开发 Springboot 作为后台开发语言调用线上合约 通

    2024年01月16日
    浏览(53)
  • 自学WEB后端02-基于Express框架完成一个交互留言板!

    提示: 浏览器V8是JavaScript的前端运行环境 Node.js 是JavaScript 的后端运行环境 Node.js 中无法调用 DOM 和 BOM等浏览器内置 API 这个作业案例包含2部分内容, 第一部分是前端 前端完成界面内容+CSS框架 第二部分是后端 完成用户留言存储,并返回 我这里为了方便放在了后端myapp目录

    2024年02月08日
    浏览(40)
  • 从零开始的QQ开放平台机器人-------Gensokyo框架部署运行开发教程合集

    大家好,我是早苗狐,一名有5年QQ机器人开发运营经验的机器人爱好者. 随着QQ为机器人开放了越来越多的接口能力,基于QQ开放平台Api能力的新框架逐渐应运而生, 本文就带给大家如何通过一系列操作,部署,运行,维护和开发一个新的QQ机器人. QQ开放平台地址: QQ开放平台 QQ开放平台

    2024年02月03日
    浏览(93)
  • 不用懂 Kubernetes 的 云原生应用管理平台

    官网 Rainbond 是一个云原生应用管理平台,使用简单,不需要懂容器、Kubernetes和底层复杂技术,支持管理多个Kubernetes集群,和管理企业应用全生命周期。主要功能包括应用开发环境、应用市场、微服务架构、应用交付、应用运维、应用级多云管理等。 Rainbond 遵循 以应用为中

    2024年02月12日
    浏览(36)
  • python后端,一个账户,多设备登录管理

    一个账号,多台设备同时登陆的问题,设计以及实现 参考这篇文章: 利用的是Redis,主设备的保存问题,可使用MySQL进行设置实现 同时允许3台设备在线 只是设计思路,数据库的使用,可以按照公司的要求 多设备 Redis实现的设计 参考 云原生内存数据库设计 Tair自研的拓展数

    2024年02月10日
    浏览(42)
  • .Net初学 创建一个巨简单的.Net7 WebApi后端框架

    visual studio 2022 以下简称vs    Visual Studio安装指南_visual studio安装教程_技术人小柒的博客-CSDN博客 sqlserver 2022 以下简称mssql        SQL Server2022 Express和SSMS下载安装教程(超详细) (baidu.com) redis Redis下载安装图文教程(Windows版_超详细)_windows redis下载_Leeway啊樺的博客-CSDN博客

    2024年02月21日
    浏览(39)
  • 从零开始实现一个C++高性能服务器框架----Hook模块

    此项目是根据sylar框架实现,是从零开始重写sylar,也是对sylar丰富与完善 项目地址:https://gitee.com/lzhiqiang1999/server-framework 项目介绍 :实现了一个基于协程的服务器框架,支持多线程、多协程协同调度;支持以异步处理的方式提高服务器性能;封装了网络相关的模块,包括

    2023年04月09日
    浏览(96)
  • 从零开始实现一个C++高性能服务器框架----Socket模块

    此项目是根据sylar框架实现,是从零开始重写sylar,也是对sylar丰富与完善 项目地址:https://gitee.com/lzhiqiang1999/server-framework 项目介绍 :实现了一个基于协程的服务器框架,支持多线程、多协程协同调度;支持以异步处理的方式提高服务器性能;封装了网络相关的模块,包括

    2023年04月08日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包