多图详解万星 Restful 框架原理与实现

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 多图详解万星 Restful 框架原理与实现

rest框架概览

我们先通过 go-zero 自带的命令行工具 goctl 来生成一个 api service,其 main 函数如下:

func main() {
 flag.Parse()
 var c config.Config
 conf.MustLoad(*configFile, &c)
 ctx := svc.NewServiceContext(c)
 server := rest.MustNewServer(c.RestConf)
 defer server.Stop()
 handler.RegisterHandlers(server, ctx)
 fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
 server.Start()
}
  1. 解析配置文件
  2. 将配置文件传入,初始化 serviceContext
  3. 初始化 rest server
  4. context 注入 server 中:
  1. 注册路由
  2. context 中的启动的 endpoint 同时注入到 router 当中
  1. 启动 server

接下来我们来一步步讲解其设计原理!Let's Go!

web框架

从日常开发经验来说,一个好的 web 框架大致需要满足以下特性:

  1. 路由匹配/多路由支持
  2. 支持自定义中间件
  3. 框架和业务开发完全解耦,方便开发者快速开发
  4. 参数校验/匹配
  5. 监控/日志/指标等服务自查功能
  6. 服务自保护(熔断/限流)

go-zero rest设计

https://github.com/zeromicro/go-zero/tree/master/rest

概览

  1. 借助 context (不同于 gin 的 context),将资源初始化好 → 保存在 serviveCtx 中,在 handler 中共享(至于资源池化,交给资源自己处理,serviveCtx 只是入口和共享点)
  2. 独立 router 声明文件,同时加入 router group 的概念,方便开发者整理代码结构
  3. 内置若干中间件:监控/熔断/鉴权等
  4. 利用 goctl codegen + option 设计模式,方便开发者自己控制部分中间件的接入

上图描述了 rest 处理请求的模式和大部分处理路径。

  1. 框架内置的中间件已经帮开发者解决了大部分服务自处理的逻辑
  2. 同时 go-zero 在 business logic 处也给予开发者开箱即用的组件(dq、fx 等)
  3. 从开发模式上帮助开发者只需要关注自己的 business logic 以及所需资源准备

下面我们来细说一下整个 rest 是如何启动的?

启动流程

上图描述了整体 server 启动经过的模块和大致流程。准备按照如下流程分析 rest 实现:

  1. 基于 http.server 封装以及改造:把 engine(web框架核心) 和 option 隔离开
  2. 多路由匹配采取 radix-tree 构造
  3. 中间件采用洋葱模型 → []Middleware
  4. http parse 解析以及匹配校验 → httpx.Parse()
  5. 在请求过程会收集指标 (createMetrics()) 以及监控埋点 (prometheus)

server engine封装

点开大图观看

engine 贯穿整个 server 生命周期中:

  1. router 会携带开发者定义的 path/handler,会在最后的 router.handle() 执行
  2. 注册的自定义中间件 + 框架中间件,在 router handler logic 前执行

在这里:go-zero 处理的粒度在 route 上,封装和处理都在 route 一层层执行

路由匹配

那么当 request 到来,首先是如何到路由这一层的?

首先在开发最原始的 http server ,都有这么一段代码:

type helloHandler struct{}
func (h *helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello, world!"))
}
func main() {
    http.Handle("/", &helloHandler{})
    http.ListenAndServe(":12345", nil)
}

http.ListenAndServe()  内部会执行到:server.ListenAndServe()

我们看看在 rest 里面是怎么运用的:

而传入的 handler 其实就是:router.NewRouter() 生成的 router。这个 router 承载了整个 server 的处理函数集合。

同时 http.Server 结构在初始化时,是把 handler 注入到里面的:

type Server struct {
 ...
 Handler Handler
}
func start(..., handler http.Handler, run func(srv *http.Server) error) (err error) {
 server := &http.Server{
  Addr:    fmt.Sprintf("%s:%d", host, port),
  Handler: handler,
 }
 ...
 return run(server)
}

在 http.Server 接收 req 后,最终执行的也是:handler.ServeHTTP(rw, req)

所以内置的 router 也需要实现 ServeHTTP 。至于 router 自己是怎么实现 ServeHTTP :无外乎就是寻找匹配路由,然后执行路由对应的 handle logic。

解析参数

解析参数是 http 框架需要提供的基本能力。在 goctl code gen 生成的代码中,handler 层已经集成了 req argument parse 函数:

// generate by goctl
func QueryAllTaskHandler(ctx *svc.ServiceContext) http.HandlerFunc {
 return func(w http.ResponseWriter, r *http.Request) {
  // custom request in .api file
  var req types.QueryAllTaskRequest
  // parse http request
  if err := httpx.Parse(r, &req); err != nil {
   httpx.Error(w, err)
   return
  }
  l := logic.NewEventLogic(r.Context(), ctx)
  resp, err := l.QueryAllTask(req)
  baseresponse.FormatResponseWithRequest(resp, err, w, r)
 }
}

进入到 httpx.Parse() ,主要解析以下几块:

https://github.com/zeromicro/go-zero/blob/master/rest/httpx/requests.go#L32:6

  1. 解析path
  2. 解析form表单
  3. 解析http header
  4. 解析json

Parse() 中的 参数校验 的功能见:

https://go-zero.dev/cn/api-grammar.html 中的 tag修饰符

Tips

学习源码推荐 fork 出来边看边写注释和心得,可以加深理解,以后用到这块功能的时候也可以回头翻阅。

项目地址

https://github.com/zeromicro/go-zero

相关文章
|
2月前
|
机器学习/深度学习 API iOS开发
探索iOS开发中的SwiftUI框架深入理解RESTful API设计原则与最佳实践
【7月更文挑战第30天】本文深入探讨了SwiftUI框架在iOS开发中的应用,分析了其对用户界面构建的简化方法及性能优化。通过比较传统UI构建方式与SwiftUI的差异,揭示了SwiftUI如何提高开发效率和用户体验。文章还讨论了SwiftUI在实际项目中的集成策略,并展望了其未来的发展方向。 【7月更文挑战第30天】在数字时代的浪潮中,RESTful API如同一座桥梁,连接着不同的软件系统。本文将探讨RESTful API的核心设计原则,揭示其背后的哲学思想,并通过实例分析展示如何将这些原则应用于实际开发中。我们将从资源定位、接口一致性到HTTP方法的恰当使用,逐一剖析,旨在为开发者提供
51 1
|
2月前
|
开发框架 JSON API
震撼发布!Python Web开发框架下的RESTful API设计全攻略,让数据交互更自由!
【7月更文挑战第22天】在Python Web开发中,设计高效的RESTful API涉及选择框架(如Flask或Django)、明确资源及使用HTTP方法(GET, POST, PUT, DELETE)来操作数据。响应格式通常是JSON,错误处理也很重要。示例展示了使用Flask创建图书管理API,包括版本控制、文档化、安全性和性能优化是最佳实践。这样的API使数据交互更顺畅。
79 2
|
3天前
|
开发框架 JSON 缓存
震撼发布!Python Web开发框架下的RESTful API设计全攻略,让数据交互更自由!
在数字化浪潮推动下,RESTful API成为Web开发中不可或缺的部分。本文详细介绍了在Python环境下如何设计并实现高效、可扩展的RESTful API,涵盖框架选择、资源定义、HTTP方法应用及响应格式设计等内容,并提供了基于Flask的示例代码。此外,还讨论了版本控制、文档化、安全性和性能优化等最佳实践,帮助开发者实现更流畅的数据交互体验。
19 1
|
23天前
|
缓存 Java 应用服务中间件
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
54 2
|
28天前
|
API 开发者 Python
"FastAPI路由大揭秘!轻松玩转URL映射,让你的Web应用路由设计既RESTful又灵活多变,秒杀传统框架的秘籍在这里!"
【8月更文挑战第31天】在Web开发中,路由是连接用户请求与后端逻辑的关键。FastAPI作为现代Python Web框架的佼佼者,以其简洁的API设计和高性能,提供了高度灵活的路由系统。本文通过开发一个博客系统的案例,详细介绍了FastAPI中路由的实现方法,包括基础路由定义、参数类型验证及路由分组与嵌套等,展示了如何轻松构建RESTful风格的URL映射,提升应用的可维护性和扩展性。
40 2
|
28天前
|
开发者 Java UED
大文件传输不再头疼:揭秘Struts 2如何轻松应对文件上传与下载难题!
【8月更文挑战第31天】在Web应用开发中,文件上传与下载至关重要。Struts 2作为主流Java EE框架,凭借Commons FileUpload及文件上传拦截器简化了相关操作。本文探讨Struts 2在文件传输上的优势,通过具体配置与代码示例,展示如何设置最大文件大小、使用`fileUpload`拦截器以及实现文件上传与下载功能。对于大文件传输,Struts 2不仅能够轻松应对,还支持上传进度显示,有效提升了用户体验。总体而言,Struts 2为文件传输提供了高效便捷的解决方案,助力开发者构建稳定可靠的Web应用。然而,在处理大文件时需兼顾网络带宽与服务器性能,确保传输顺畅。
42 0
|
28天前
|
API 网络安全 数据库
Web2py框架如何颠覆传统的RESTful API开发?掌握这些技巧,让你的开发效率飞跃!
【8月更文挑战第31天】Web2py是一款全栈Python Web框架,适用于快速开发复杂交互的Web应用。本文将介绍如何使用Web2py创建RESTful API,包括设置新控制器、定义RESTful路由、处理数据库交互、确保API安全性、编写文档与使用Swagger、测试API以及部署时的注意事项。Web2py的高度抽象和易用性使其成为实现RESTful API的理想选择,帮助开发者专注于业务逻辑而非技术细节。
24 0
|
2月前
|
JSON API 网络架构
揭秘!Python Web框架下的RESTful API设计,为何成为互联网新宠?
【7月更文挑战第24天】在互联网快速发展背景下,RESTful API以其简洁性和可扩展性成为应用间通信的首选。REST强调资源为核心,利用HTTP方法处理CRUD操作,促进前后端分离,提高开发效率。Python的Flask框架支持轻松构建RESTful API,通过路由、请求和响应机制实现。示例代码展示了如何使用Flask创建、读取和更新用户信息。Python Web框架因其丰富的工具和库,简化RESTful API开发,适应微服务架构需求,在互联网发展中扮演重要角色。
51 3
|
4月前
|
Web App开发 JavaScript Cloud Native
构建高效可扩展的RESTful API:Node.js与Express框架实践指南构建未来:云原生架构在企业数字化转型中的关键作用
【5月更文挑战第29天】 在数字化时代的驱动下,后端服务架构的稳定性与效率成为企业竞争力的关键。本文深入探讨了如何利用Node.js结合Express框架构建一个高效且可扩展的RESTful API。我们将从设计理念、核心模块、中间件应用以及性能优化等方面进行系统性阐述。通过实例引导读者理解RESTful接口设计的最佳实践,并展示如何应对大规模并发请求的挑战,确保系统的高可用性与安全性。
|
4月前
|
缓存 API 数据库
构建高效Python Web应用:Flask框架与RESTful API设计原则
【5月更文挑战第20天】 在现代Web开发中,构建一个轻量级且高效的后端服务至关重要。本文将深入探讨如何使用Python的Flask框架结合RESTful API设计原则来创建可扩展和易于维护的Web应用程序。我们将通过分析Flask的核心特性,以及如何利用它来实现资源的合理划分、接口的版本控制和请求处理优化等,来指导读者打造高性能的API服务。文中不仅提供了理论指导,还包括了实践案例,旨在帮助开发者提升开发效率,并增强应用的稳定性和用户体验。