解读开源 Go HTTP 框架 Hertz

2023-11-10

前言

在参与 Hertz 框架的开发迭代过程中,对 Hertz 的主库也越来越熟悉。接下来的几篇文章我将分别解析 Hertz 的服务注册、服务发现和负载均衡拓展,最后会使用适配于 Hertz 的 etcd 拓展进行实战,欢迎大家关注。

Hertz

Hertz 是一个超大规模的企业级微服务 HTTP 框架,具有高易用性、易扩展、低时延等特点。

Hertz 默认使用自研的高性能网络库 Netpoll,在一些特殊场景中,相较于 go net,Hertz 在 QPS、时延上均具有一定优势。

在内部实践中,某些典型服务,如框架占比较高的服务、网关等服务,迁移 Hertz 后相比 Gin 框架,资源使用显著减少,CPU 使用率随流量大小降低 30%—60%

关于 Hertz 更多的信息可移步至 cloudwego/hertz

服务注册拓展

Hertz 支持自定义注册模块,使用者可自行扩展集成其他注册中心,该扩展定义在 pkg/app/server/registry 下。

拓展接口与注册信息

服务注册接口定义与实现

服务注册的接口定义和大部分服务注册的实现类似,含有两个方法,一个为服务注册,另一个为服务取消注册。

// Registry is extension interface of service registry.
type Registry interface {
        Register(info *Info) error
        Deregister(info *Info) error
}

这两个方法在 register.go 的后续代码中进行了实现。

// NoopRegistry
type noopRegistry struct{}

func (e noopRegistry) Register(*Info) error {
        return nil
}

func (e noopRegistry) Deregister(*Info) error {
        return nil
}

register.go 中还提供了一个空的 Registry 实现,为 Hertz 配置中服务注册的默认值。

// NoopRegistry is an empty implement of Registry
var NoopRegistry Registry = &noopRegistry{}

同时也是 Hertz 配置中服务注册的默认值。

func NewOptions(opts []Option) *Options {
    options := &Options{
        // ...
        Registry: registry.NoopRegistry,
    }
    options.Apply(opts)
    return options
}

注册信息

registry.go 中提供了关于注册信息的定义,在使用 WithRegistry进行配置服务注册时会初始化注册信息并传入到 Register 方法中进行后续逻辑的执行。这些字段仅为建议,具体的使用取决于自己的设计。

// Info is used for registry.
// The fields are just suggested, which is used depends on design.
type Info struct {
        // ServiceName will be set in hertz by default
        ServiceName string
        // Addr will be set in hertz by default
        Addr net.Addr
        // Weight will be set in hertz by default
        Weight int
        // extend other infos with Tags.
        Tags map[string]string
}

服务注册的时机

在每次调用 Spin 方法时,我们都会运行 initOnRunHooks ,而在 initOnRunHooks 中包含我们服务注册的时机。

func (h *Hertz) initOnRunHooks(errChan chan error) {
        // add register func to runHooks
        opt := h.GetOptions()
        h.OnRun = append(h.OnRun, func(ctx context.Context) error {
                go func() {
                        // delay register 1s
                        time.Sleep(1 * time.Second)
                        if err := opt.Registry.Register(opt.RegistryInfo); err != nil {
                                hlog.SystemLogger().Errorf("Register error=%v", err)
                                // pass err to errChan
                                errChan <- err
                        }
                }()
                return nil
        })
}

在调用 initOnRunHooks 时,我们会将服务注册的匿名函数添加到 runHooks 中,在此函数中我们先启动一个 goroutine ,这里我们会通过 time.Sleep 延迟一秒,当异步注册时,服务不一定会启动,所以会延迟一秒来等待服务启动。在此之后调用 Register 并将配置中的 Info 传入。若注册时出现错误则将错误传递到 errChan 中。

服务取消注册的时机

在接收到程序退出的信号时 Hertz 会进行优雅退出调用 Shutdown 方法,在此方法中会进行服务取消注册。首先并发执行 executeOnShutdownHooks 并等待它们直到等待超时或完成执行。接着就将查看是否有注册的服务,若有则调用 Deregister 进行服务取消注册。

func (engine *Engine) Shutdown(ctx context.Context) (err error) {
   if atomic.LoadUint32(&engine.status) != statusRunning {
      return errStatusNotRunning
   }
   if !atomic.CompareAndSwapUint32(&engine.status, statusRunning, statusShutdown) {
      return
   }

   ch := make(chan struct{})
   // trigger hooks if any
go engine.executeOnShutdownHooks(ctx, ch)

   defer func() {
      // ensure that the hook is executed until wait timeout or finish
select {
      case <-ctx.Done():
         hlog.SystemLogger().Infof("Execute OnShutdownHooks timeout: error=%v", ctx.Err())
         return
      case <-ch:
         hlog.SystemLogger().Info("Execute OnShutdownHooks finish")
         return
      }
   }()

   if opt := engine.options; opt != nil && opt.Registry != nil {
      if err = opt.Registry.Deregister(opt.RegistryInfo); err != nil {
         hlog.SystemLogger().Errorf("Deregister error=%v", err)
         return err
      }
   }

   // call transport shutdown
if err := engine.transport.Shutdown(ctx); err != ctx.Err() {
      return err
   }

   return
}

总结

在这篇文章中我们了解到了 Hertz 可支持高度自定义服务注册拓展的实现,并解析了 Hertz 是如何将其集成在了框架的核心部分。

最后,如果文章对你有帮助,就点赞分享一下吧,谢谢!

参考

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解读开源 Go HTTP 框架 Hertz 的相关文章

  • 在电子邮件中使用协议相对 URL 安全吗?

    关于在 HTML 中使用协议相对 URL 已有讨论 1 但是电子邮件呢 电子邮件客户端或 Gmail 等服务提供商在 HTML 电子邮件中使用时是否会删除或修改协议相对 URL 1 我可以将所有 http 链接更改为 吗 https sta
  • 把自己限制在HTTP1.0有什么用吗?

    我负责构建一些工具来帮助最终用户测试为什么他们的浏览器可能无法与网站配合使用 我被告知它可能不起作用的原因之一是 需要 HTTP1 1 这一行 我浏览了大多数浏览器选项 只浏览了 IE 版本 6 及更高版本 even 9 允许您禁用 HTT
  • 使用矩阵参数创建 GET 请求

    我将使用的网络服务需要矩阵参数 http tester com v1 customers lastname Jackson firstname Tim bookingreference 7Y9UIY 而不是通常的 http tester c
  • 通过 HTTPS 包含 Twitter Widgets.js

    当我们包含以下内容时 我在我们网站上的 HTTPS 服务页面上的混合内容方面遇到了一个小问题http platform twitter com widgets js http platform twitter com widgets js
  • WCF - 进行多次调用时随机客户端超时

    我有一个WPF客户端通过以下方式请求数据WCF服务托管于IIS 7 服务方法调用存储过程 SQL 2012 using EF检索一些数据 由于需要加载大量数据 因此客户端会多次调用服务方法 以 分解 数据加载并避免大量负载和超时 我们使用生
  • 如何让 NSURLRequest 获取 Twitter 请求令牌?

    我正在尝试使用以下代码从 Twitter 获取请求令牌 NSMutableURLRequest mURLRequest NSMutableURLRequest alloc initWithURL NSURL URLWithString ht
  • 从开放的 HTTP 流中读取数据

    我正在尝试使用 NET WebRequest WebResponse 类来访问 Twitter 流 API 此处 http stream twitter com spritzer json 我需要能够打开连接并从打开的连接中增量读取数据 目
  • 反向代理受 NTLM 保护的网站

    如何将请求代理到受 NTLM 保护的网站 例如团队基金会 and 共享点 我不断得到401 身份验证错误 根据这篇 Microsoft TechNet 文章 https www microsoft com technet prodtechn
  • 对过期会话进行休息调用:HTTP 401 响应导致浏览器显示登录窗口

    我编写了一个 HTML 5 应用程序 它使用 AngularJS 并与在 Tomcat 上运行的 Java REST 后端进行交互 我使用 Spring Security 来处理登录和安全性 当用户进入网站时 他将被转发到登录页面 该页面创
  • Golang 优雅地关闭 HTTP 服务器并进行错误处理

    我正在让我的 HTTP 服务器正常关闭 我从帖子中获取了提示here https stackoverflow com questions 39320025 how to stop http listenandserve 并且到目前为止已经像
  • 为什么使用HTTP协议时需要指定端口号?

    即使我们使用HTTP协议 为什么还需要用IP地址指定端口号 例如 http xyz 8080 这到底是什么意思 我们已经知道 在使用 HTTP 时 请求将在端口 80 上提供服务 那么为什么我们要显式指定端口呢 HTTP 的默认端口为 80
  • 除了 GET 和 POST 之外,如何从浏览器向 RESTful 应用程序发送任何内容?

    我没有得到 RESTful 的东西 是的 我知道如何从浏览器向我的应用程序发送 GET 请求 这是通过 URL 链接 a href user someone 并且还可以通过form方法发送POST请求 a
  • MPMoviePlayerController 播放 YouTube 视频

    如何在 iPhone 上的 MPMoviePlayerController 中播放 YouTube 视频 同时避免进入全屏模式 这个问题已经在这里提出 MPMoviePlayerController 正在播放 YouTube 视频吗 htt
  • 在 iOS 中,http 204 响应返回空白页面,有办法阻止这种情况吗?

    以前可能有人问过这个问题 但我似乎找不到解决方案 所以如果是这种情况 我深表歉意 我正在开发一个使用express的简单节点应用程序 其中一个帖子路由返回 http 204 并发送它 下面是我的代码 router post id funct
  • Android - API 请求

    我开发了一个应用程序 它也在 iPhone 上 问题出在 api 请求上 我为所有请求设置了超时 有时会出现 30 60 秒的中断 看起来这个应用程序执行了几个请求 然后就中断了 一直超时 大约 45 秒后一切正常 不知道是服务器问题还是安
  • AJAX 发送数据到 Node.js 服务器

    我尝试使用 AJAX 将数据发送到 Node js 服务器 但不断遇到同样的问题 即接收问题 这是客户端 JavaScript AJAX 代码 var objects function return new XMLHttpRequest f
  • 404 标头 - HTTP 1.0 还是 1.1?

    为什么我能找到的几乎每个例子 包括这个问题 https stackoverflow com questions 437256 sending a 404 error in php大约一年前 说 404 标头应该是HTTP 1 0 404 N
  • JS 库请求的常见 HTTP 标头是什么?

    使用JavaScript 框架原型 http www prototypejs org 我注意到 Ajax 请求通过一个名为X Requested With 其他 JavaScript 库 如 jQuery dojo 和 YUI 是否会向其
  • iOS WKWebView 处理文件下载

    我面临以下问题 在 Web 界面中 文件下载是通过锚标记触发的 如下所示 a href bla blabla a 虽然 Safari 浏览器可以处理此请求并打开一个对话框来处理文件 但 WKWebView 将此视为普通链接并且不对其执行任何
  • Django HTTPS 和 HTTP 会话

    我使用 Django 1 1 1 和 ssl 重定向中间件 通过 HTTPS 创建的会话数据 身份验证等 在站点的 HTTP 部分中不可用 无需将整个站点设置为 HTTPS 即可使其可用的最佳方法是什么 这是设计使然 您无法轻易更改 当通过

随机推荐

  • Windows下安装nvm及搭建Angular环境的步骤整理

    环境 操作系统 windows 8 1 安装nvm nvm windows 下载https github com coreybutler nvm windows releases 我把nvm noinstall zip解压到c dev nv
  • PS2汉化1 字库处理

    引语 其实字库处理很难说有一个统一的方法 不同的程序都需要不同方法来处理 关于常见位图字库的详细信息 下面是字库存在于ELF ERX文件时的处理思路 字模替换 最天真朴素 最通用的处理方式 适用于原字库大小能够塞下汉化所用的全部文字的情况
  • XSS、CSRF攻击以及预防手段

    文章目录 XSS 反射型 持久型 DOM型 XSS如何防御 CSRF XSS XSS全程Cross Site Scripting 名为跨站脚本攻击 是一种常见于 Web 应用中的计算机安全漏洞 恶意攻击者往 Web 页面里嵌入恶意的客户端脚
  • 【VBA编程】VBA基础语法(一)

    一 VBA中的数据类型 VBA里的数据类型有 字节型 Byte 整数型 Integer 长整数型 Long 单精度浮点型 Single 双精度浮点型 Double 货币型 Currency 小数型 Decimal 字符串型 String 日
  • 《数据清洗》第五章操作实例

    案例一介绍 通过Kettle工具 消除CSV文件merge csv中完全重复的数据 1 打开Kettle工具 创建转换 通过使用Kettle工具 创建一个转换repeat transform 并添加 CSV文件输入 控件 唯一行 哈希值 控
  • 把多页Word文档缩小打印到同一张纸上

    方法一 首先要确定纸张的大小和方向 系统默认的是 A4 纸 方向纵向 如果要改变 可单击 文件 页面设置 进行相应的更改 单击 插入 文本框 横排 然后在刚才新建的文档中画出一个文本框 大小大约为这页纸的四分之一 然后将鼠标放到该文本框的边
  • 关于某些特殊时候按钮disabled属性失效时的解决办法

    今天遇到了一个BUG 导致下一步按钮中的属性即时有disabled时 点击按钮依然会触发按钮的点击事件 以下为下一步按钮的JS代码 下一步 btn step click function e if this hasClass layui b
  • 常见排序算法--合并排序

    思路 将一个无序的序列分组 直至分为每两个元素一组 如果有单个元素剩余 则可以剩余的单个元素自己一组 小组内排序 然后合并成一个有序的序列 例子 排序过程如图所示 图片摘选自 https blog csdn net ZY cat artic
  • 腾讯云nginx配置ssl证书实现https

    1 申请证书 2 下载证书 签发后 里面包含nginx 1 1 域名 bundle crt 2 2 域名 key 3 配置nginx文件 在配置ssl证书之前 要确保你的nginx已经安装了ssl模块 如果没有请安装 gt sbin ngi
  • rstudio导入txt文件_r语言怎么读取txt文件

    展开全部 1 r语言62616964757a686964616fe59b9ee7ad9431333431376533读取txt文件的方法 首先根据下图图片中的命令代码进行输入 2 然后这样就可以读取txt文件了 结果图如下 3 R读取csv
  • 模拟网盘(基于多线程TCP)

    题目描述 模拟一个网盘实现以下功能 用户可以注册 登录 上传和下载文件 用户可以实现类似 ls的功能查询文件信息 多用户间文件可以共享 要求 基于TCP协议 server端要用多线程实现 在linux下用C语言实现 需要实现的功能 服务器端
  • 基于java的支付宝即时到账支付

    java实现支付宝即时到账支付 演示地址 支付宝电脑网站支付 支持回调 支付成功后即可回到自己自定义的回调页面 下载地址 java实现支付宝即时到账支付 源码世界 下载后在本地只需把你的几个配置参数改成自己的即可完美实现在线支付 应用ID
  • Java封装的概念

    封装是面向对象的三大特征之一 封装 继承 多态 概念 封装就是将类里的某些信息隐藏 不允许外部程序直接调用 可以对成员变量更准确的控制 举例 通过以上代码 可以看到 如过X类的成员变量直接被调用 那么可能会出现赋值越界的情况 年龄不可能小于
  • MongoDB分片实战(一):集群搭建

    随笔 97 文章 9 评论 337 MongoDB分片实战 一 集群搭建 环境准备 Linux环境 主机 OS 备注 192 168 32 13 CentOS6 3 64位 普通PC 192 168 71 43 CentOS6 2 64位
  • Maven 4、JDK配置

    当你的idea中有多个jdk的时候 就需要指定你编译和运行的jdk 在settings xml中配置
  • 使用命令把类打成jar包

    测试用类 public class Hello public static void main String args System out println hello world 一般的Jar包 生成class文件 在命令行中输入下面代码
  • windows桌面应用自动化测试

    1 AutoIt3 原理 使用spy抓应用的hwnd 根据hwnd获取窗口信息 模拟发送鼠标按键 移动窗口实现自动化操作 缺点 获取到的信息少 编程实现复杂 2 UIAutomation msdn介绍 Microsoft UI Automa
  • STM32 USB DFU功能

    STM32 USB DFU功能 工具的安装配置 CubeMX上配置 完善接口 工具使用 HEX固件转为DFU文件 更新固件 DFU特点 工程代码 DFU的全称为 DownLoad Firmware Update即固件升级 以下配置以STM3
  • Junit5单元测试

    配置 Maven配置 我用的spring版本是2 2 2 其实引入一个就行
  • 解读开源 Go HTTP 框架 Hertz

    前言 在参与 Hertz 框架的开发迭代过程中 对 Hertz 的主库也越来越熟悉 接下来的几篇文章我将分别解析 Hertz 的服务注册 服务发现和负载均衡拓展 最后会使用适配于 Hertz 的 etcd 拓展进行实战 欢迎大家关注 Her