千万级入口服务[Gateway]框架设计(一)

本文将以技术调研模式编写,非技术同学可跳过。

文章目录

    • 背景
    • 问题[不涉及具体业务]
    • 目标
    • 技术选型
      • 语言
      • 框架模式
        • 实现一:go 原生组件
        • Demo 实现
        • Benchwork 基准性能
        • 小结
        • 实现二:开源 go-plugin
    • 附录
      • 入口服务演变

背景

在历史架构的迭代中,服务的入口级模块从雨后春笋到方兴未艾、以至于现在的如火如荼,最终成为服务定位中的,基础服务之一。

在这里插入图片描述
其核心功能一般是对流量进行清洗、漏斗、染色、追踪…等公共、通用性功能。

问题[不涉及具体业务]

现行的入口模块存在以下几个问题,急需进行改造、升级。

在这里插入图片描述

  • 框架过重
    • 框架控制单次请求中下游服务的调用模型
    • 框架显式支持串行调用,隐式支持并行调用
    • 框架嵌套基础组件SDK,部分功能为黑盒

目标

针对现行模块中暴露出的核心问题,从问题出发,推敲、构建预期框架模式特性。
在这里插入图片描述

  • 轻量
    • 收敛、抽象模块功能,解锁业务与框架之间的绑定、耦合
    • 提倡并行调用,串行辅助的调用策略
    • 承接云原生可观测组件,深度、全面刨析服务状态,杜绝黑盒、盲区
    • 支撑 兜底、降级…等必备手段

技术选型

语言

在这里插入图片描述

PHP 服务逐步迁移至 Goland,技术栈进行转换、升级。

框架模式

对于入口服务调度模块,随着下游业务的扩展,业务方的自定义需求会越来越多,越来越频繁。
为了能够让业务方自定义开发各自的业务逻辑,需要提供一种开发模式或者技术,能够由其他业务开发人员进行扩展,而不需重新编译整个模块的代码。(类似 Nginx 的模式,这也是中小企业,入口服务直接使用 代理 或者 Nginx 的原因)

在这里插入图片描述

考虑到插件模式可以帮助我们扩展原有程序的功能,同时它与原有工程是解耦的,可以独立开发,故小结如下:

  • 插件模式的核心功能/优势
    • 为系统提供灵活的扩展能力
      • 主服务 与 插件 的代码解耦,独立开发
      • 主服务 只关注插件的接口,不关注实现细
    • 不侵入系统现有功能
      • 主服务 动态引入插件,因而可以自由定制所需的能力,避免部署包的体积过大
      • 插件可以独立升级

实现一:go 原生组件

服务在执行过程中动态加载部分应用程序的能力(可能基于用户定义的配置)在某些设计中可能是一个有用的构建块。特别是,因为应用程序和动态加载的函数可以直接共享数据结构,所以插件可以实现独立部分的非常高性能的集成。
在这里插入图片描述

Go 附带一个内置于标准库中的插件包。这个包让我们编写的 Go 程序被编译成共享库而不是可执行二进制文件;此外,它还提供了用于加载共享库和从中获取符号的简单函数。

import (
	"plugin"
)

然而,插件机制有许多明显的缺点,在设计过程中应该仔细考虑。例如:

  • 插件目前仅在 Linux、FreeBSD 和 macOS 上受支持,因此它们不适合用于可移植的应用程序。
  • 使用插件的应用程序可能需要仔细配置,以确保程序的各个部分在文件系统(或容器映像)的正确位置可用。相比之下,部署由单个静态可执行文件组成的应用程序非常简单。
  • 当某些包可能在应用程序开始运行很长时间后才初始化时,关于程序初始化的推理会更加困难。
  • 攻击者可以利用加载插件的应用程序中的错误来加载危险或不受信任的库。
  • 除非程序的所有部分(应用程序及其所有插件)都使用完全相同版本的工具链、相同的构建标签以及某些标志和环境变量的相同值进行编译,否则很可能会发生运行时崩溃。

Demo 实现

实现分为三部分:主程序、组件程序、公共库。公共库可与主程序所属库共同,组件程序进行包引用即可。

  • 主程序
package main

import (
	"fmt"
	"os"
	"plugin"

	util "XXXX"
)

func main() {
	req := util.Req{Str: "A"}

	// 0. qt flow dispatch
	var mod string
	if mod = Dispatch(req.Str); len(mod) < 1 {
		fmt.Println("don't deal str")
		os.Exit(1)
	}
	// 1. open the so file to load the symbols
	plug, err := plugin.Open(mod)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	// 2. look up a symbol (an exported function or variable)
	symExecute, err := plug.Lookup("ModExecute")
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	// 3. Assert that loaded symbol is of a desired type
	modExecute, ok := symExecute.(util.ModExecute)
	if !ok {
		fmt.Println("unexpected type from module symbol")
		os.Exit(1)
	}
	// 4. use the module
	modExecute.Init(&req)
	modExecute.Check()
	modExecute.Execute()
	res := modExecute.Out()
	fmt.Println("main run success res msg:", res.Msg)
}

func Dispatch(str string) string {
	var mod string
	switch str {
	case "A":
		mod = "./X/A.so"
	case "B":
		mod = "./X/B.so"
	default:
	}
	return mod
}

运行:go run main.go

  • 组件程序
package main

import (
	"fmt"

	util "XXXX"
)

type A struct {
}

func (s A) Init(req *util.Req) {
	fmt.Println("a module:Init:", req.Str)
}

func (s A) Check() {
	fmt.Println("a module:Check")
}

func (s A) Execute() {
	fmt.Println("a module:Execute")
}

func (s A) Out() util.Res {
	fmt.Println("a module:Out")
	return util.Res{Msg: "ok"}
}

var ModExecute A

运行: go build -buildmode=plugin -o X/A.so main-plugin.go

  • 公共库
package util

type ModExecute interface {
	Init(*Req) // 前置初始化操作
	Check()    // 流量签名&鉴权
	Execute()  // 执行操作
	Out() Res  // 输出
}

type Req struct {
	Str string
}

type Res struct {
	Msg string
}

Benchwork 基准性能

  • 基本性能十分优秀,32 核机器简单 Demo 基准性能测试
go test -bench BenchmarkMainDeal -benchtime=5s -benchmem
   87883             69740 ns/op            4998 B/op          6 allocs/op
PASS
ok      XXXXX  6.822s

小结

总之,这些限制意味着:在实践中,应用程序及其插件必须全部由一个人或系统的一个组件一起构建。在那种情况下,对于那个人或组件来说,生成空白导入所需插件集的 Go 源文件然后以通常的方式编译静态可执行文件可能更简单。

由于这些原因,许多用户认为传统的进程间通信 (IPC) 机制(例如套接字、管道、远程过程调用 (RPC)、共享内存映射或文件系统操作)可能更适合,尽管性能开销很大。

实现二:开源 go-plugin

相关 Demo 实现、Benchwork 基准性能、小结 见后续文章。


附录

  • https://eli.thegreenplace.net/2021/plugins-in-go/

入口服务演变

互联网初期的时候,是没有入口或前置服务的概念的。
请求服务都是从端上发起到后段处理的链路。随着业务种类及规模的膨胀,出现了以下的问题:

  • 端上承接大量的请求发起任务重担
  • 各业务接受请求后,都需要流量清洗、作弊判定…等公共处理举措
  • 网络带宽等资源数量级的增加
  • 用户体验对服务平响、数据质量…等性能要求的提升

基于这些棘手的问题,急需在服务入口提供一公共模块,进行一些前置操作,在节省资源、业务维护成本的同时,提升服务性能、质量。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Apache Kafka学习

目录 一、简介 1.概念&#xff1a; 2.kafka四大API&#xff1a; 3.Kafka消费模式 4.Kafka的基础架构 5.kafka文件存储方式 二、特性 三、优点 1.解耦 2.异步处理 3.流量削峰 4.数据持久化 5.顺序保证 6.可恢复性 四、名词解释 五、QA Q:如何保证数据高可靠、不…

从美颜算法到AI美颜SDK:美丽的背后隐藏着什么?

在年轻人的生活中&#xff0c;通过美颜SDK类型的美颜工具进行拍摄已经成为了一种全新的文化现象。时下&#xff0c;AI美颜、美颜SDK讨论热点极高&#xff0c;那么大家知道美颜算法和AI美颜到底有什么不同吗&#xff1f;它们背后隐藏着什么样的技术和思想&#xff1f; 一、美颜算…

在Windows11平台安装JDK11(双11)

目录 引言一、安装前说明1.系统要求2.多版本安装 二、JDK11安装三、安装成功验证1.验证2.Path环境变量 总结 引言 本文主要是详细讲解在 Windows 11 系统上安装 JDK 11&#xff0c;安装时有一些注意事项需要说明。与 JDK 8 的安装过程有少许不一样。 一、安装前说明 1.系统要…

Atair 柱状比例图

如何熟练掌握可视化库和应对使用过程的疑难问题&#xff1f; 基本用法不妨访问 GeeksforGeeks 疑难问题优先搜索 https://stackoverflow.com 尽量使用官方文档&#xff1a; numpy的学习访问 https://numpy.org/doc/stable/user/index.html 例如&#xff1a; 一则 altair 使用过…

小程序中半屏打开其他小程序,开发者工具调试半屏

前言&#xff1a; 有需要是在当前小程序中&#xff0c;点击操作时&#xff0c;如果他没有注册会员&#xff0c;则强制去另一个小程序去注册会员&#xff0c;注册成功在返回&#xff0c;在这期间&#xff0c;打开另一个小程序是半屏来展示的。 实现效果&#xff1a; 在a小程序中…

阿里4年测试经验分享 —— 测试外包干了3年后,我废了...

去年国庆&#xff0c;我分享了一次一位阿里朋友的技术生涯&#xff0c;大家反响爆蓬&#xff0c;感觉十分有意思&#xff0c;今天我来分享一下我另一位朋友的真实经历&#xff0c;是不是很想听&#xff1f; 没错&#xff0c;我这位朋友是曾经外包公司的测试开发&#xff0c;而…

React新版扩展特性

目录 Hooks 三个常用的Hook State Hook Effect Hook Ref Hook Context Router 6 声明式路由 编程式路由导航 Hooks (1) Hook是react 18.8.0版本新增的特性/语法 (2) 可以让我们在函数式组件中使用state以及其他的react特性 三个常用的Hook (1) State Hook: React.useSt…

使用javacv中的ffmpeg实现录屏

今天突发奇想&#xff0c;想自己写一个录屏的软件&#xff0c;上次写了一个专门录音的Demo&#xff0c;但是要把声音和视频放到一起合成一个mp4文件&#xff0c;着实有一点艰难&#xff0c;所以就打算使用ffmpeg来写一个&#xff0c;而这篇博客中会顺便谈一谈我碰到的各种坑。 …

HarmonyOS学习路之开发篇—Java UI框架(StackLayout)

StackLayout StackLayout直接在屏幕上开辟出一块空白的区域&#xff0c;添加到这个布局中的视图都是以层叠的方式显示&#xff0c;而它会把这些视图默认放到这块区域的左上角&#xff0c;第一个添加到布局中的视图显示在最底层&#xff0c;最后一个被放在最顶层。上一层的视图…

数据湖仓一体化架构:探究新一代数据处理的可能性

一、引言 随着大数据的快速发展&#xff0c;企业不断寻求高效、灵活和经济的方法来处理和管理海量数据。在这种背景下&#xff0c;数据湖和数据仓库这两种不同的架构模式各自展现出其独特的优势。而数据湖仓一体化架构&#xff0c;是对这两种模式优势的综合&#xff0c;为企业…

wenda+fess问答系统

1 安装conda 2 创建环境 conda activate --name wenda python3.8 3 安装依赖工具包 pip install -r requirements/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple pip install torch BeautifulSoup4 torchvision torchaudio pdfminer.six -i https://pypi.t…

【乐观锁与悲观锁】—— 每天一点小知识

&#x1f4a7; 乐观锁与悲观锁 \color{#FF1493}{乐观锁与悲观锁} 乐观锁与悲观锁&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞见云的博客&#x1f390; &#x1f433; 《数据结构与算法》专栏的文章图文并茂&…

美团买菜基于 Flink 的实时数仓建设

摘要&#xff1a;本文整理自美团买菜实时数仓技术负责人严书&#xff0c;在 Flink Forward Asia 2022 实时湖仓专场的分享。本篇内容主要分为四个部分&#xff1a; 背景介绍 技术愿景和架构设计 典型场景、挑战与应对 未来规划 点击查看原文视频 & 演讲PPT 一、背景介绍…

设置全局loading

为什么要设置全局loading&#xff1f; 在项目开发过程中&#xff0c;请求接口的时候延迟没有数据&#xff0c;页面感觉狠卡顿&#xff0c;这个时候就要用loading来做一个延迟界面。 但是每个界面都写loading的话就会很复杂&#xff0c;所以今天给大家带来了一个全局loading的…

JMeter+Ant+jenkins搭建接口自动化测试环境

目录 前言&#xff1a; 1.ant简介 2. 构建ant环境 3.JMeter与Ant集成 4. 报告优化 5.jenkins持续集成 前言&#xff1a; JMeter是一个开源的性能测试工具&#xff0c;可以用于测试Web应用程序或API接口的性能&#xff0c;支持多种通信协议和数据格式。Ant是一个构建工具&…

基于卫星星历计算卫星在CGCS2000大地坐标系中的坐标

目录 一、北斗系统概述 1.空间星座 2.坐标系统 3.时间系统 二、实验目的 三、实验内容 四、实验过程 五、实验结果 一、北斗系统概述 1.空间星座 北斗卫星导航系统简称北斗系统&#xff0c;英文缩写为 BDS&#xff0c;其空间星座由 5 颗地球静止轨道&#xff08;GEO&…

学会使用这些Lumion照片级渲染技巧,秒出大片

Lumion 是一种渲染软件&#xff0c;可帮助建筑师以清晰、感性的方式传达他们的设计。十年来&#xff0c;人们发现 Lumion 的每个新版本都有新的功能、工作流程和控制方法。他们可以在 Revit、SketchUp 或其他 BIM 程序等软件中建模&#xff0c;并将模型导入 Lumion 进行渲染&am…

基于stm32作品设计:多功能氛围灯、手机APP无线控制ws2812,MCU无线升级程序

文章目录 一、作品背景二、功能设计与实现过程三、实现基础功能&#xff08;一&#xff09;、首先是要选材&#xff08;二&#xff09;、原理图设计&#xff08;二&#xff09;、第一版本PCB设计&#xff08;三&#xff09;、焊接PCB板&#xff08;四&#xff09;编写单片机程序…

作为自动化测试工程师,这4个自动化测试阶段你真的知道吗?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 阶段一&#xff1…

Kubernetes集群添加新集群节点

Kubernetes集群添加新集群节点 添加worker节点 参考文档https://gitee.com/open-hand/kubeadm-ha/blob/release-1.21/docs/02/%E6%B7%BB%E5%8A%A0%20worker%20%E8%8A%82%E7%82%B9.md 添加工作节点与集群安装时初始化工作节点一样,可以在主节点上执行&#xff0c;也可以在要加…