Go 语言项目开发实战
孔令飞
腾讯云专家工程师,前 Red Hat、联想云工程师
41030 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 61 讲
Go 语言项目开发实战
15
15
1.0x
00:00/00:00
登录|注册

29|控制流(下):iam-apiserver服务核心功能实现讲解

通过 Redis 的 Sub/Pub 机制实现数据一致性
实现调用链功能
插件化选择 JSON 库
通过使用 context.Context 传递扩展参数来实现函数参数的扩展
实现并发处理查询结果的模板
通过统一的返回函数 WriteResponse 实现统一的返回格式
使用 ObjectMeta 结构体作为所有资源的公共属性
所有 REST 资源支持公共属性和资源自有属性
通过统一的资源元数据和规范的代码存放路径来管理 API 版本
支持 API 版本号放在 URL 中的方式
根据需要选择性地加载中间件
支持插件化地加载 Gin 中间件
自动调用健康检查接口以实现更方便的健康检查
通过直接请求健康检查接口来检查服务健康状态
使用 net/http 包提供的 Shutdown 方法来处理现有请求并关闭服务
通过拦截 SIGINTSIGTERM 信号实现优雅关停
其他特性
并发处理模板
统一的返回
统一的资源元数据
API 版本
插件化加载中间件
健康检查
优雅关停
iam-apiserver 服务核心功能实现讲解

该思维导图由 AI 生成,仅供参考

你好,我是孔令飞。
上一讲,我介绍了 iam-apiserver 是如何构建 Web 服务的。这一讲,我们再来看下 iam-apiserver 中的核心功能实现。在对这些核心功能的讲解中,我会向你传达我的程序设计思路。
iam-apiserver 中包含了很多优秀的设计思想和实现,这些点可能比较零碎,但我觉得很值得分享给你。我将这些关键代码设计分为 3 类,分别是应用框架相关的特性、编程规范相关的特性和其他特性。接下来,我们就来详细看看这些设计点,以及它们背后的设计思想。

应用框架相关的特性

应用框架相关的特性包括三个,分别是优雅关停、健康检查和插件化加载中间件。

优雅关停

在讲优雅关停之前,先来看看不优雅的停止服务方式是什么样的。
当我们需要重启服务时,首先需要停止服务,这时可以通过两种方式来停止我们的服务:
在 Linux 终端键入 Ctrl + C(其实是发送 SIGINT 信号)。
发送 SIGTERM 信号,例如 kill 或者 systemctl stop 等。
当我们使用以上两种方式停止服务时,都会产生下面两个问题:
有些请求正在处理,如果服务端直接退出,会造成客户端连接中断,请求失败。
我们的程序可能需要做一些清理工作,比如等待进程内任务队列的任务执行完成,或者拒绝接受新的消息等。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

iam-apiserver服务核心功能实现详细介绍了iam-apiserver服务的核心功能实现,包括应用框架相关的特性、编程规范相关的特性和其他特性。文章首先介绍了应用框架相关的特性,包括优雅关停、健康检查和插件化加载中间件的实现方法,并给出了相关的示例代码。其次,文章介绍了编程规范相关的特性,包括API版本、统一的资源元数据、统一的返回和并发处理模板。另外,iam-apiserver中所有的资源都是 REST 资源,且REST 资源的属性也进一步规范化了,包括公共属性和资源自有的属性。文章还介绍了统一的返回函数的实现方式,确保API接口的返回格式是统一的。除此之外,文章还介绍了插件化选择 JSON 库、调用链实现、数据一致性等其他特性。通过具体的代码示例和实现细节,本文详细介绍了iam-apiserver中的核心功能实现,对于想要深入了解iam-apiserver的开发者来说,是一篇非常有价值的文章。文章内容涵盖了JSON库的选择、调用链实现以及使用context.Context传递参数等技术特点,为读者提供了全面的技术视角。 文章总结了iam-apiserver的关键功能实现,包括优雅关停、健康检查、插件化加载中间件、API版本标识、统一的资源元数据、统一的返回格式、并发处理模板、插件化选择JSON库、调用链实现以及数据一致性。通过这些功能的实现,iam-apiserver能够保证进程关停时的任务完成、避免服务异常启动、统一API版本标识、共享功能代码、处理并发逻辑、灵活选择JSON库、实现调用链功能以及保证数据一致性。此外,文章还提出了课后练习,鼓励读者思考更好的并发处理方式,并尝试给iam-apiserver增加新的可配置的Gin中间件,以实现API限流的效果。整体而言,本文为读者提供了深入了解iam-apiserver核心功能实现的宝贵资源,涵盖了丰富的技术内容,对技术开发者具有重要参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 语言项目开发实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(35)

  • 最新
  • 精选
  • helloworld
    Extend和ExtendShadow设计真的很棒,敢问灵感从哪里来的👍

    作者回复: 来源于实际开发的痛点,不过还有一种设计方法。将模型层也接口化。这个IAM项目后面会实现

    2021-08-11
    2
    5
  • Realm
    这两篇老师的总结很受启发。 练习: 1 在项目中一般还是使用goroutine比较多,或者atomic,或者读写锁; 2 限流可以使用令牌桶和漏桶,或者自适应限流; 问: 一个业务通过A->B->C完成,通过requestID可以串起来,假如严格一点,是不是还要搞个parnent-request-id ?

    作者回复: 不用的,日志系统会按时间戳排序的

    2021-08-01
    4
    5
  • 宙斯
    健康检查这里有两个疑问: 1 配置了健康检查会阻塞,不会运行 eg.Wait() ,这是故意阻塞在ping这里的吗? 2 健康检查ping函数for中,我查看到逻辑是这样的, a) 在启动时web服务还未启动,会出错err,每隔1s运行一次, b) 当服务正常启动后,这是能请求通畅,然后就return nil,只运行一次就不再运行了。 这个逻辑有些疑惑,健康检查不应该总是运行的么? 代码位置:iam/internal/pkg/server/genericapiserver.go 版本:当前master版本

    作者回复: 1. 是的 2. 这个是启动时的健康检查。服务的健康检查,可以通过一些旁路系统来保证,比如:kubernetes健康检查机制等。不过,你说这是个很好的思路。我记录个TODO,以后有需要更新下。

    2021-08-30
    3
  • helloworld
    项目源码中的var _ UserSrv = (*userService)(nil) 的目的是为了在编译阶段检查 userServer 类型是否实现了 UserSrv 的接口, 如果没有实现则panic, (*userService)(nil)这种语法是出自哪里呢, 在哪里能找到这个语法的详细说明呢, 我找了半天没找到, 只知道(*userService)(nil)用来表示类型*userService的零值.

    作者回复: Go基本语法中有。 var _ UserSrv = (*userService)(nil) 是一个赋值语句,右边是*userService类型的零值,赋值给左边的变量,如果变量类型不metch,编译器会报错

    2021-08-13
    3
    2
  • xgt132
    老师你好:在 ”并发处理模板“这一模块时,当遇到错误就会返回nil, 此时剩下的协程会不会还在继续运行,这样是不是浪费了系统资源呢

    作者回复: 这个模板有点问题,我优化下

    2022-08-07归属地:广东
    1
  • NULL
    "这样,我们下次需要新增参数的话,只需要调用 context 的 WithValue 方法:" 这样不好吧, 传递的sex可能会被修改. 也不清晰, 不知道传递了什么数据 官方文档也说 "Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions." https://pkg.go.dev/context

    作者回复: 实际情况是很多项目是这么弄得。controller-runtime会从context中传递Logger。我觉得只要传递一些通用的,感知性非常强的,就可以。WithValue确实不应该乱用

    2022-08-04归属地:广东
    1
  • Geek_63505f
    老师请问下这里 下面那个run方法是启动命令行的命令吗?我看a.cmd.Execute()命令里面是执行os.Args[1:] 。 apiserver.NewApp("iam-apiserver").Run() func (a *App) Run() { if err := a.cmd.Execute(); err != nil { fmt.Printf("%v %v\n", color.RedString("Error:"), err) os.Exit(1) } }

    作者回复: 是命令行的启动命令。

    2022-01-27
    2
    1
  • Geek_433b2b
    孔老师,你好。我是 Go 语言初学者,在并发处理模板这块有个疑问: 为什么在协程中不是直接对参数 user 赋值:user.TotalPolicy = policies.TotalCount,最后直接返回 users。而是重新创建一个 User 对象?包括在 ListWithBadPerformance 中也是重新创建了一个对象。 我写了个 demo 是可以正常赋值的。这样做的话不就可以不使用 map 了吗,而且也能保证顺序。

    作者回复: user是个临时变量,下一次for循环值就变了

    2021-12-29
    1
  • ppd0705
    请问SQL文件里面时间字段为什么是如下语句?和实际gorm的逻辑不一致 ```sql `createdAt` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `updatedAt` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', ``` 实际表现应该是如下 ```sql `createdAt` timestamp NOT NULL DEFAULT current_timestamp(), `updatedAt` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), ```

    作者回复: 感谢反馈! SQL写反了,我修复下!

    2021-10-03
    1
  • XI
    go func() { // 将服务在 goroutine 中启动 if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("listen: %s\n", err) } }() 优雅关停机这段代码,当前面有nginx的时候是无法拿到客户端ip的,拿到的ip 会是nginx的ip 详请可见gin 的r.run 方法

    作者回复: nginx可以配置成透传客户端IP

    2021-09-23
    2
    1
收起评论
显示
设置
留言
35
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部