项目升级必备(web通用)

这篇具有很好参考价值的文章主要介绍了项目升级必备(web通用)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1:雪花算法(分布式id生成器)

时间因子毫秒级别,机器id

(long整型的64bit位结构)

项目升级必备(web通用),go,web

雪花算法的主要目标是在分布式环境下生成全局唯一的ID,以避免ID冲突问题。以下是雪花算法的优缺点:

优点:

  1. 唯一性: 雪花算法生成的ID在同一时刻、同一数据中心、同一机器上都是唯一的,且具有较高的唯一性。

  2. 分布式: 算法支持分布式环境,每个节点都能够独立生成ID,无需中心化的ID生成服务。

  3. 有序性: 生成的ID是趋势递增的,因为雪花算法使用了时间戳作为其中的一部分,所以在一定程度上保持了ID的有序性。

  4. 简单高效: 算法相对简单,执行效率高,适用于高并发场景。

  5. 可读性: 雪花算法生成的ID通常是一个64位的整数,其中包含了时间戳等信息,便于人类阅读和理解。

缺点:

  1. 时钟回拨问题: 如果系统时钟发生回拨,有可能导致生成的ID不是严格递增的,这可能引发一些问题。为了解决这个问题,需要进行额外的时钟同步处理。

  2. 依赖系统时钟: 雪花算法依赖系统时钟,如果系统时钟不稳定,可能会影响ID的生成。

  3. ID大小: 生成的ID是64位的整数,相对于一些其他算法(如UUID)来说,占用的存储空间相对较大。

  4. 不适用于短时间内大量生成ID的场景: 在极短时间内大量生成ID可能会导致序列号部分耗尽,需要等待下一个时间戳。

总体而言,雪花算法在大多数分布式系统中表现良好,尤其适用于需要生成全局唯一ID并保持一定有序性的场景。然而,在一些特殊情况下,如时钟回拨等问题,可能需要额外的处理来保证其稳定性。

2:请求参数绑定

结构体参数统一格式

例如:

//ParamSignUp注册参数定义
type ParamSignUp struct {
   Username   string `json:"username" binding:"required"`
   Password   string `json:"password" binding:"required"`
   RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}

参数绑定使用

p := new(models.ParamSignUp)
err := ctx.ShouldBindJSON(p)

Validator 是用于验证数据的工具,它可以确保数据符合一定的规范、格式或业务逻辑。在参数绑定后,你可以使用 Validator 来验证数据的有效性。

3:validator简单的验证器与中英文包翻译

err.(validator.ValidationErrors)//验证错误
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		//注册一个获取json tag的自定义方法
		//将解析字段的 JSON tag 并返回对应的名称,以便在校验失败时提供更友好的错误提示。
		v.RegisterTagNameFunc(func(field reflect.StructField) string {
			name := strings.SplitN(field.Tag.Get("json"), ",", 2)[0]
			if name == "-" {
				return ""
			}
			return name
		})
		zhT := zh.New() //中文翻译包
		enT := en.New()
		uni := ut.New(enT, zhT, enT) //创建一个通用的翻译器
		var ok bool
		trans, ok = uni.GetTranslator(locale) //获取指定语言环境的翻译器
		if !ok {
			return fmt.Errorf("uni GetTranslator(%s) failed", locale)
		}
		//注册翻译器
		switch locale {
		case "en":
			err = enTranslations.RegisterDefaultTranslations(v, trans)
		case "zh":
			err = zhTranslations.RegisterDefaultTranslations(v, trans)
		default:
			err = enTranslations.RegisterDefaultTranslations(v, trans)
		}
// removeTopStruct 去除提示信息中的结构体名称,校验失败时提供更友好的错误提示
func removeTopStruct(flieds map[string]string) map[string]string {
   res := map[string]string{}
   for flied, err := range flieds {
      res[flied[strings.Index(flied, ".")+1:]] = err
   }
   return res
}

5:jwt基于token的认证

JWT分为三个部分,header(头部) payload (负载) signature (签名);头部和负载部,是用base64URL转成字符串的,签名是用头部指定的算法转成字符串的 ,所以jwt数据通常有两个小数点

JWT一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,token也可直接被用于认证,也可被加密。JWT原理就是,服务器认证后,生成一个json格式的对象 ,发送给客户端,然后每次客户端发送请求都需要带着token

Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息。

流程:

这个token在每次请求时传递给服务端,它应该被保存在请求头里

// 定义JWT的过期时间,这里以24小时为例
const TokenExpireDuration = time.Hour * 24

// CustomSecret 用于加盐的字符串
var CustomSecret = []byte("今晚的月色好美啊")

type CustomClaims struct {
	UserId               int64  `json:"user_id"`
	Username             string `json:"username"`
	jwt.RegisteredClaims        //内嵌标准的声明
}

// GenToken 生成JWT
func GenToken(userId int64, username string) (aToken, rToken string, err error) {
	// 创建一个我们自己的声明
	claims := CustomClaims{
		userId,
		username, // 自定义字段
		jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(TokenExpireDuration)),
			Issuer:    "my-project", // 签发人
		},
	}
	//获取aToken,加密并获得完整字符串 使用指定的secret签名
	aToken, err = jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(CustomSecret)
	//rToken 不需要存任何自定义数据
	rToken, err = jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.StandardClaims{
		ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(),
		Issuer:    "my-project", // 签发人
	}).SignedString(CustomSecret)
	return
}

// ParseToken 解析JWT
func ParseToken(tokenString string) (*CustomClaims, error) {
	var mc = new(CustomClaims)
	// 如果是自定义Claim结构体则需要使用 ParseWithClaims 方法
	token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) {
		// 直接使用标准的Claim则可以直接使用Parse方法
		//token, err := jwt.Parse(tokenString, func(token *jwt.Token) (i interface{}, err error) {
		return CustomSecret, nil
	})
	if err != nil {
		return nil, err
	}
	// 对token对象中的Claim进行类型断言
	if token.Valid { // 校验token
		return mc, nil
	}
	return nil, errors.New("invalid token")
}

// refreshToken 刷新 accessToken
func RefreshToken(aToken, rToken string) (newAToken, newRToken string, err error) {
	// refreshToken 无效返回
	_, err = jwt.Parse(rToken, func(token *jwt.Token) (i interface{}, err error) {
		// 直接使用标准的Claim则可以直接使用Parse方法
		//token, err := jwt.Parse(tokenString, func(token *jwt.Token) (i interface{}, err error) {
		return CustomSecret, nil
	})
	if err != nil {
		return
	}
	//从旧的access token中解析出claims数据
	var claims CustomClaims
	_, err = jwt.ParseWithClaims(aToken, &claims, func(token *jwt.Token) (i interface{}, err error) {
		// 直接使用标准的Claim则可以直接使用Parse方法
		//token, err := jwt.Parse(tokenString, func(token *jwt.Token) (i interface{}, err error) {
		return CustomSecret, nil
	})

	v, _ := err.(*jwt.ValidationError)
	//accessToken过期 refreshToken没有过期  创建一个新的 accessToken
	if v.Errors == jwt.ValidationErrorExpired {
		return GenToken(claims.UserId, claims.Username)
	}
	return
}

6:swagger接口文档

(1):写注释(main方法和接口函数之前)

注意:注册路由前需要添加

// 注册 swagger api 相关路由
r.GET("/swagger/*any", gs.WrapHandler(swaggerFiles.Handler))

(2):安装swagger

go get -u github.com/swaggo/swag/cmd/swag

(3):swag init

成功之后会生成docx文件夹

项目升级必备(web通用),go,web

(4):访问http://127.0.0.1:8080/swagger/index.html

进入swagger UI页面接口测试

7:测试函数

名字以路由接口名_test.go,例如登录测试:login_test.go

func TestLoginHandler(t *testing.T) {
	gin.SetMode(gin.TestMode)
	r := gin.Default()
	url := "/api/v1/login"
	r.POST(url, LoginHandler)
	body := `{
		"username": "zhangsan",
		"password": "123456"
	}`
	req, _ := http.NewRequest(http.MethodPost, url, bytes.NewReader([]byte(body)))
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
}
  • 第一个部分是 1 个 bit:0,符号位

  • 第二个部分是 41 个 bit:表示的是时间戳。系统控制

  • 第三个部分是(5 个 bit:表示的是机房 ID,10001) +  (5 个 bit:表示的是机器 ID,1 1001)。

  • 第四个部分是 12 个 bit:表示的序号,就是某个机房某台机器上这一毫秒内同时生成的 id 的序号,0000 00000000。

  • //设置唯一ID生成器的起始时间和机器ID。
    func Init(startTime string, machineId int64) (err error) {
    	var st time.Time
    	st, err = time.Parse("2006-01-02", startTime)
    	if err != nil {
    		return
    	}
    	//将解析后的起始时间转换为毫秒级别的时间戳,并将其赋值给 sf.Epoch
    	sf.Epoch = st.UnixNano() / 1000000
    	node, err = sf.NewNode(machineId)
    	return
    }
    
    func GenID() int64 {
    	return node.Generate().Int64()
    }

    优点:

  • 唯一性: 雪花算法生成的ID在同一时刻、同一数据中心、同一机器上都是唯一的,且具有较高的唯一性。

  • 分布式: 算法支持分布式环境,每个节点都能够独立生成ID,无需中心化的ID生成服务。

  • 有序性: 生成的ID是趋势递增的,因为雪花算法使用了时间戳作为其中的一部分,所以在一定程度上保持了ID的有序性。

  • 简单高效: 算法相对简单,执行效率高,适用于高并发场景。

  • 时钟回拨问题: 如果系统时钟发生回拨,有可能导致生成的ID不是严格递增的,这可能引发一些问题。为了解决这个问题,需要进行额外的时钟同步处理。

  • 依赖系统时钟: 雪花算法依赖系统时钟,如果系统时钟不稳定,可能会影响ID的生成。

  • ID大小: 生成的ID是64位的整数,相对于一些其他算法(如UUID)来说,占用的存储空间相对较大。

  • 不适用于短时间内大量生成ID的场景: 在极短时间内大量生成ID可能会导致序列号部分耗尽,需要等待下一个时间戳。

    • 可读性: 雪花算法生成的ID通常是一个64位的整数,其中包含了时间戳等信息,便于人类阅读和理解。

    • 用户使用用户名密码来请求服务器

    • 服务器进行验证用户的信息

    • 服务器通过验证发送给用户一个token

    • 客户端存储token,并在每次请求时附送上这个token值

    • 服务端验证token值,并返回数据文章来源地址https://www.toymoban.com/news/detail-830094.html

到了这里,关于项目升级必备(web通用)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 从零开始基于go-zero的go web项目实战-01项目初始化

    导语 Go 是 Google 开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言,go语言的特点: 语法简洁 Go语言简单易学,学习曲线平缓 代码风格统一 执行性能好 开发效率高 等等… 在Go语言中,有很多高性能的web框架:gin、beego、iris等。作为后起之秀,近年来

    2024年02月16日
    浏览(48)
  • 如何设计一个优秀的 Go Web 项目目录结构

    Go 语言作为一门高效、简洁、并发安全的语言,越来越受到开发者们的青睐,特别是在 Web 开发及云原生领域。而对于一个大型的 Go Web 项目而言,一个优秀的目录结构设计是必不可少的。它可以帮助我们更好地组织代码、减少冗余、提高可维护性和可扩展性。 在本文中,我

    2024年02月12日
    浏览(95)
  • 基于go语言gin框架的web项目骨架

    节省时间与精力,更高效地打造稳定可靠的Web项目:基于Go语言和Gin框架的完善Web项目骨架。无需从零开始,直接利用这个骨架,快速搭建一个功能齐全、性能优异的Web应用。充分发挥Go语言和Gin框架的优势,轻松处理高并发、大流量的请求。构建可扩展性强、易于维护的代码

    2024年02月08日
    浏览(46)
  • 初始化一个Gin框架的Go-Web项目

    使用到的第三方库 gin Gin 框架 viper 配置文件管理 cors 跨域资源请求配置 gorm ORM 库 zap 日志记录 Go 语言程序的入口点 main.go 文件 使用 flag 读取配置文件路径参数,默认当前目录下 使用 viper 读取 config.ini 配置文件初始化初始数据 初始化随机数种子 初始化数据库 声明启动程序

    2024年02月09日
    浏览(52)
  • Go开发使用bee工具生成beego框架工程代码、运行web项目以及beego中内置模板函数列表

        GO开发中使用bee工具生成beego框架工程代码,在这之前假定你已经成功安装好了Beego环境搭建和bee工具,Windows下Beego环境搭建和bee工具的安装使用_bee命令 windows-CSDN博客 然后在命令行或者在git bash中进入到GOPATH的src目录,执行bee new 工程名称,来生成一个beego框架工程目录:

    2024年04月29日
    浏览(38)
  • 汽车之家Unity前端通用架构升级实践

    背景介绍 随着之家3D虚拟化需求的增加,各产品线使用Unity引擎的项目也越来越多,新老项目共存,代码维护成本也随之增加。代码质量参差加之代码规范仍没有完全统一产生高昂学习成本进一步加重了项目维护负担。 为应对这些问题,我们决定借助主机厂数科产品线销冠神

    2024年02月03日
    浏览(36)
  • 20款奔驰S350商务型升级前排座椅通风系统,夏天必备的功能

    通风座椅的主动通风功能可以迅速将座椅表面温度降至适宜程度,从而确保最佳座椅舒适性。该功能启用后,车内空气透过打孔皮饰座套被吸入座椅内部,持续时间为 8 分钟。然后,风扇会自动改变旋转方向,将更凉爽的环境空气从座椅后部和下部导向乘坐者。气流通过座椅

    2024年02月13日
    浏览(37)
  • 已解决Python.selenium爬虫必备设置永久禁止谷歌浏览器自动升级(亲测有效)

    问题描述:selenium框架自动化操作浏览器的时候,需要安装浏览器驱动 WebDriver ,而 WebDriver 驱动需要对应浏览器的版本才运行。但是我们常用的谷歌浏览器是有自动更新的,就会经常导致 WebDriver 版本和谷歌浏览器版本对应不上,运行代码就会出现如下报错信息。 每次去下载

    2024年02月10日
    浏览(57)
  • 嵌入式必备的WEB知识

    嵌入式要学习Wed前端吗?答案是要的,不需要深入学习,只需要简单了解即可。为什么要学习? 原因如下: 可以远程控制和管理设备:通过简单的Web知识,嵌入式系统可以建立Web界面,使得用户可以通过浏览器进行远程控制和管理设备,无需直接连接物理接口。 显示和呈现

    2024年01月19日
    浏览(43)
  • Go使用vscode开发,必备的插件及最常用快捷键和代码自动补全

    为进行Markdown文档编写提供很多快捷键和自动补全功能,使vscode可以完全代替Typora。 边写边看到Markdown渲染之后的样子,在 Preview 界面按住鼠标右键可以打开功能栏,选择Open in Browser可以将文件在浏览器打开,还可以选择生成HTML或者PDF等。 在Markdown中快捷插入图片,复制图片

    2024年03月10日
    浏览(95)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包