首页>>后端>>Golang->【Go 语言框架与实现 学习资料】第三届字节跳动青训营

【Go 语言框架与实现 学习资料】第三届字节跳动青训营

时间:2023-12-01 本站 点击:0

第三届字节跳动青训营讲师非常用心给大家整理了课前、中、后的学习内容,同学们自我评估,选择性查漏补缺,便于大家更好的跟上讲师们的节奏,祝大家学习愉快,多多提问交流~

第十三节:深入浅出 RPC 框架

概述

本节课程主要分为四个方面:

RPC 相关的基本概念

RPC 框架的分层设计

衡量 RPC 框架的一些核心指标

字节内部 RPC 框架 Kitex 实践分享

课前部分主要罗列课程中涉及到的概念。对于不熟悉的概念,同学们可以提前查询预习;

课中部分主要罗列每一部分的关键思路,帮助同学们跟上课程的进度;

课后部分是一些问题,帮助同学们在课后梳理本课程的重点。

课前

RPC 的基本概念

RPC的概念模型:User、User-Stub、RPC-Runtime、Server-Stub、Server

来自论文《Implementing Remote Procedure Calls》

IDL(Interface Definition Language) 文件

Thrift

Protobuf

生成代码

编解码(序列化/反序列化)

通信协议

应用层协议

网络通信

TCP

UDP

blocking IO

unblocking IO

IO multiplexing

signal driven IO

asynchronous IO

IO 网络模型

传输层协议

RPC 框架分层设计

编解码层

兼容性

通用型

性能

语言特定格式

文本格式

二进制编码

TLV 编码:Thrift 使用 TLV 编码

Varint 编码:Protobuf 使用 Varint 编码

数据格式:

选项:

传输协议层

以 Thrift 的 THeader 协议为例讲解

特殊结束符

变长协议:length+body

消息切分

协议构造

网络通信层

吞吐高

延迟低

网络库

核心指标

RPC 框架的核心指标

稳定性

BackupRequest

负载均衡

重试

熔断

限流

超时

保障策略

请求成功率

长尾请求

易用性

开箱即用

周边工具

扩展性

观测性

Log

Metric

Tracing

内置观测性服务

高性能

字节内部 Kitex 实践分享

Kitex 整体架构

自研网络库 Netpoll

性能优化:

网络库优化

编解码优化

合并部署

课中

基本概念

相比本地函数调用,RPC调用需要解决的问题

函数映射

数据转换成字节流

网络传输

一次 RPC 的完整过程

RPC 带来的问题将由 RPC 框架来解决

服务宕机如何感知?

遇到网络异常应该如何应对?

请求量暴增怎么处理?

RPC 框架分层设计

编解码层

数据格式

语言特定格式:例如 java.io.Serializable

文本格式:例如 JSON、XML、CSV 等

二进制编码:常见有 Thrift 的 BinaryProtocol,Protobuf,实现可以有多种形式,例如 TLV 编码 和 Varint 编码

选型考察点

空间开销

时间开销

兼容性

通用型

性能

生成代码和编解码层相互依赖,框架的编解码应当具备扩展任意编解码协议的能力

协议层

以 Thrift 的 THeader 协议为例

LENGTH 字段 32bits,包括数据包剩余部分的字节大小,不包含 LENGTH 自身长度

HEADER MAGIC 字段16bits,值为:0x1000,用于标识 协议版本信息,协议解析的时候可以快速校验

FLAGS 字段 16bits,为预留字段,暂未使用,默认值为 0x0000

SEQUENCE NUMBER 字段 32bits,表示数据包的 seqId,可用于多路复用,最好确保单个连接内递增

HEADER SIZE 字段 16bits,等于头部长度字节数/4,头部长度计算从第14个字节开始计算,一直到 PAYLOAD 前(备注:header 的最大长度为 64K)

PROTOCOL ID 字段 uint8 编码,取值有: - ProtocolIDBinary = 0 - ProtocolIDCompact = 2

NUM TRANSFORMS 字段 uint8 编码,表示 TRANSFORM 个数

TRANSFORM ID 字段 uint8 编码,表示压缩方式 zlib or snappy

INFO ID 字段 uint8 编码,具体取值参考下文,用于传递一些定制的 meta 信息

PAYLOAD 消息内容

协议解析

网络通信层

阻塞 IO 下,耗费一个线程去阻塞在 read(fd) 去等待用足够多的数据可读并返回。

非阻塞 IO 下,不停对所有 fds 轮询 read(fd) ,如果读取到 n <= 0 则下一个循环继续轮询。

第一种方式浪费线程(会占用内存和上下文切换开销),第二种方式浪费 CPU 做大量无效工作。而基于 IO 多路复用系统调用实现的 Poll 的意义在于将可读/可写状态通知和实际文件操作分开,并支持多个文件描述符通过一个系统调用监听以提升性能。 网络库的核心功能就是去同时监听大量的文件描述符的状态变化(通过操作系统调用),并对于不同状态变更,高效,安全地进行对应的文件操作。

RPC 框架核心指标

稳定性

保障策略

熔断

限流

超时控制

从某种程度上讲超时、限流和熔断也是一种服务降级的手段 。

请求成功率

负载均衡

重试

长尾请求

BackupRequest

易用性

开箱即用

合理的默认参数选项、丰富的文档

周边工具

生成代码工具、脚手架工具

扩展性

Middleware:middleware 会被构造成一个有序调用链逐个执行,比如服务发现、路由、负载均衡、超时控制等

Option:作为初始化参数

核心层是支持扩展的:编解码、协议、网络传输层

代码生成工具也支持插件扩展

观测性

三件套:Log、Metric 和 Tracing

内置观测性服务,用于观察框架内部状态

当前环境变量

配置参数

缓存信息

内置 pprof 服务用于排查问题

高性能

连接池和多路复用:复用连接,减少频繁建联带来的开销

高性能编解码协议:Thrift、Protobuf、Flatbuffer 和 Cap'n Proto 等

高性能网络库:Netpoll 和 Netty 等

字节内部 Kitex 实践分享

框架文档 Kitex

自研网络库 Netpoll,背景:

a.  原生库无法感知连接状态 b.  原生库存在 goroutine 暴涨的风险

扩展性:支持多协议,也支持灵活的自定义协议扩展

性能优化,参考 字节跳动 Go RPC 框架 KiteX 性能优化实践

a.  网络优化

i.  调度优化  ii.  LinkBuffer 减少内存拷贝,从而减少 GC  iii.  引入内存池和对象池

b.  编解码优化

i.  Codegen:预计算提前分配内存,inline,SIMD等ii.  JIT:无生产代码,将编译过程移到了程序的加载(或首次解析)阶段,可以一次性编译生成对应的 codec 并高效执行

合并部署

a.  微服务过微,引入的额外的传输和序列化开销越来越大 b.  将强依赖的服务统计部署,有效减少资源消耗

课后

行业内各个流行的 RPC 框架的优劣对比

从第三章节 RPC 的核心指标来看,Kitex 还有哪些功能是欠缺或者需要加强的?

了解微服务的新趋势 ServiceMesh,以及 RPC 框架和 ServiceMesh 的关系

关于 RPC 框架,业界有哪些新的趋势和概念?

Netpoll 的优势在哪?相比其他高性能网络库例如 Netty 还有什么不足?

Flatbuffer 和 Cap'n Proto 等编解码协议为什么高性能?

参考文献

官方文档 Kitex Netpoll

字节跳动 Go RPC 框架 KiteX 性能优化实践_架构_字节跳动技术团队_InfoQ精选文章

字节跳动微服务架构体系演进_架构_字节跳动技术团队_InfoQ精选文章

第十四节:HTTP 框架修炼之道

概述

本节课程主要分为四个方面:

HTTP 协议相关知识

HTTP 框架的设计与实现

HTTP 框架的优化手段

企业实践

课前部分主要罗列课程中涉及到的概念。对于不熟悉的概念,同学们可以提前查询预习;课后部分是一些问题,帮助同学们在课后梳理本课程的重点。

课前

HTTP 协议

HTTP 协议出现背景

HTTP 协议是什么

HTTP 协议有什么

可参考百度百科

尝试写一个 hello world 服务器

可尝试用 gin 写一个 hello world 程序,达到以下效果

HTTP 框架中常见概念

框架路由:根据请求的 URI 选择对应的处理函数。

命名参数:形如 :name这类叫做命名参数,命名参数只匹配单个路径段:

Pattern: /user/:user /user/gordon              match(user = gordon) /user/you                 match(user = you) /user/gordon/profile      no match /user/                    no match

通配参数:形如 *`action`**这类叫做通配参数,就像名字所暗示的那样,它们匹配所有内容。因此,它们必须始终位于模式的末尾:

Pattern: /src/*filepath /src/                     match(filepath = "") /src/somefile.go          match(filepath = somefile.go) /src/subdir/somefile.go   match(filepath = subdie/somefile.go)

首先匹配 HTTP 方法

静态路由: 精确匹配注册的路由,如:/a/b/c、/a/b/d

参数路由:

路由修复: 如果只注册了 /a/b,但是访问的 URI 是 /a/b/,那可以提供自动重定向到 /a/b 能力;同样,如果只注册了 /a/b/,但是访问的 URI 是 /a/b,那可以提供自动重定向到 /a/b/ 能力

冲突路由:同时注册 /a/b 和 /:id/b,并设定优先级。比如:当请求 URI 为 /a/b 时,优先匹配静态路由 /a/b

什么是框架中间件,可参考 gin,kratos

Golang

sync.Pool 用法

网络库

C10K Problem

Select,Poll,Epoll

Epoll ET、LT 区别

字节跳动自研网络库 netpoll,netpoll-examples

SIMD

SIMD 是什么,可参考维基百科

Improving performance with SIMD intrinsics in three use cases

课后作业

为什么 HTTP 框架做要分层设计?分层设计有哪些优势与劣势。

现有开源社区 HTTP 框架有哪些优势与不足。

中间件还有没有其他实现方式?可以用伪代码说明。

完成基于前缀路由树的注册与查找功能?可以用伪代码说明。

路由还有没有其他的实现方式?

第十五节:微服务架构原理与治理实践

概述

本课程内容主要分为以下4个方面:

微服务架构介绍

微服务架构的背景由来、架构概览、基本要素

微服务架构原理及特征

微服务架构的基本组件、工作原理、流量特征

核心服务治理功能

核心的服务治理功能,包括流量治理、服务均衡、稳定性治理

字节跳动服务治理实践

字节跳动在微服务架构稳定性治理中,对请求重试策略的探索及实践

为了帮助大家更好地预习及理解本节课程,该学员手册列出了课前、课中、及课后这三个阶段所涉及到的专业内容大纲,其中课前部分供同学们提前预习参考,课中部分给出了课程大纲,帮助同学们整理思路,课后部分列出一些扩展性的问题让同学们进一步延伸思考。

课前

微服务架构介绍

系统架构的演进历史

单体架构

垂直应用架构

分布式架构

SOA架构

微服务架构

微服务架构的三大要素

服务治理

可观测性

安全

微服务架构原理及特征

微服务架构中的基本概念及组件

服务、实例......

服务间通信

RPC、HTTP

服务注册及服务发现

核心服务治理功能

服务发布

蓝绿部署

灰度发布(金丝雀发布)

流量治理

负载均衡

Round Robin

Ring Hash

Random

稳定性治理

限流

熔断

过载保护

降级

字节跳动服务治理实践

请求重试的意义

请求重试的难点

课中

微服务架构介绍

系统架构的演进历史

单体架构

All in one process

垂直应用架构

按照业务线垂直划分

分布式架构

抽出与业务无关的公共模块

SOA架构

面向服务

微服务架构

彻底的服务化

微服务架构概览

网关

服务配置和治理

链路追踪和监控

微服务架构的三大要素

服务治理(本课程内容)

服务注册

服务发现

负载均衡

扩缩容

流量治理

稳定性治理

可观测性

日志采集

日志分析

监控打点

监控大盘

异常报警

链路追踪

安全

身份验证

认证授权

访问令牌

审计

传输加密

黑产攻击

微服务架构原理及特征

微服务架构中的基本概念及组件

服务

一组具有相同逻辑的运行实体

实例

一个服务中的每个运行实体

实例与进程的关系

没有必然对应关系,一般一对一或者一对多

常见的实例承载形式

进程、VM、k8s pod......

服务间通信

微服务之间通过网络进行通信

常见的通信协议包括 HTTP、RPC

服务注册及服务发现

基本问题

服务间调用中,如何指定下游服务实例的地址?

简单方案

本地 DNS 存在缓存,导致延迟

DNS 没有负载均衡

不支持服务探活检查

DNS 不能指定端口

没有任何动态能力

有多个实例下游实例怎么办?

直接指定 ip:port?

使用 DNS?

服务注册发现

新增一个统一的服务注册中心,用于存储服务名到服务实例之间的映射关系

旧服务实例下线前,从服务注册中心删除该实例,下线流量

新服务实例上线后,在服务注册中心注册该实例,上线流量

微服务流量特征

统一网关入口

外网通信多数采用 HTTP,内网通信多数采用 RPC(Thrift, gRPC)

核心服务治理功能

服务发布

何为服务发布

让一个服务升级运行新的代码的过程

服务发布难点

服务不可用

服务抖动

服务回滚

蓝绿部署

将服务分成两个部分,分别先后发布

简单、稳定

但需要两倍资源

灰度发布(金丝雀发布)

先发布少部分实例,接着逐步增加发布比例

不需要增加资源

回滚难度大,基础设施要求高

流量治理

流量控制

在微服务架构中,可以从各个维度对端到端的流量在链路上进行精确控制

控制维度

地区维度

集群维度

实例维度

请求维度

负载均衡

Round Robin

Random

Ring Hash

Least Request

稳定性治理

限流

限制服务处理的最大 QPS,拒绝过多请求

熔断

中断请求路径,增加冷却时间从而让故障实例尝试恢复

过载保护

在负载高的实例中,主动拒绝一部分请求,防止实例被打挂

降级

服务处理能力不足时,拒绝低级别的请求,只响应线上高优请求

字节跳动服务治理实践

请求重试的意义

降低错误率

降低长尾延时

容忍暂时性错误

避开下游故障实例

网络抖动、下游负载高、下游机器宕机......

重试是有意义的,可以避免偶发性的错误,提高 SLA

通常没有重试意义

本地函数调用

远程函数调用

重试的意义

请求重试的难点

假设调用时间一共1s,经过多少时间开始重试?

随着调用链路的增加,重试次数呈指数级上升

POST 请求可以重试吗?

幂等性

重试风暴

超时设置

重试策略

对于可能超时(或延时高)的请求,重新向另一个下游实例发送一个相同的请求,并等待先到达的响应

返回特殊的 status code,表示“请求失败,但别重试”

设定一个重试比例阈值(例如 1%),重试次数占所有请求比例不超过该阈值

限制重试比例

防止链路重试

Hedged Requests

重试效果验证

字节跳动重试组件能够极大限制重试发生的链路放大效应

课后

结合 CAP 等原理,思考微服务架构有哪些缺陷?

微服务是否拆分得越“微”越好?为什么?

Service Mesh 这一架构是为了解决微服务架构的什么问题?

有没有可能有这样一种架构,从开发上线运维体验上是微服务,但实际运行又类似单体服务?

参考文献

A Design Analysis of Cloud-based Microservices Architecture at Netflix

字节跳动微服务架构体系演进

微服务架构的一知半解

原文:https://juejin.cn/post/709966539865561500


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Golang/5912.html