Apinto 网关进阶教程,插件开发入门指南

Apinto 是基于Go语言,由 Eolink 自主研发的一款高性能、可扩展、易维护的云原生 API 网关。Apinto 能够帮助用户简单、快速、低成本、低风险地实现:系统微服务化、系统集成、向合作伙伴、开发者开放功能和数据。

通过 Apinto,企业能够专注于自身业务的发展,并且让企业间能互相借力,实现共赢。

借助 Apinto 强大的插件拓展能力,用户可像乐高积木一样根据需要自行拓展Apinto 的插件,丰富 Apinto 的能力。

本篇文章将给大家介绍如何开发 Apinto插件,自行拓展 Apinto 网关能力

前置知识

插件执行流程

插件系统定义了 Access 、Proxy 两个插件执行周期,其执行阶段定义如下:

  • Access:客户端请求 Apinto,将请求转发给上游服务前执行;
  • Proxy:将响应返回给客户端前执行;

请求从客户端发出,到达路由进行转发前,按顺序从上到下进行每个插件的 Access 执行阶段,转发获取响应后,从下到上执行每个插件的 Proxy 执行阶段。

插件执行流程如下图,请求处理即为转发前执行的操作,响应处理即为转发获得响应后的操作。

 

插件实现 UML 图

插件实现采用工厂设计模式,系统初始化时,自动将插件工厂注册到插件管理器中,当有新增插件/修改插件需求时,插件工厂实例会创建插件执行器实例。

开发插件

为了更加直观介绍自定义开发插件,本文将以开发 响应重写 插件为例,完整代码可参考 [Apinto 项目响应插件]

定义插件配置

开发插件前,先确定插件的功能和界限,根据需求定义插件配置格式,此处以 响应重写 插件为例。


{
    "status_code":0,
    "body":"",
    "body_base64":true,
    "headers":{},
    "match":{
        "code":[]
    }
}

根据上述配置,定义插件配置结构体。


type Config struct {
 StatusCode int               `json:"status_code" label:"响应状态码" minimum:"100" description:"最小值:100"`
 Body       string            `json:"body" label:"响应内容"`
 BodyBase64 bool              `json:"body_base64" label:"是否base64加密"`
 Headers    map[string]string `json:"headers" label:"响应头部"`
 Match      *MatchConf        `json:"match" label:"匹配状态码列表"`
}

type MatchConf struct {
 Code []int `json:"code" label:"状态码" minimum:"100" description:"最小值:100"`
}

实现插件执行器

1. 定义执行器结构


type ResponseRewrite struct {
 drivers.WorkerBase
 statusCode int
 body       string
 headers    map[string]string
 match      *MatchConf
}

2. 实现 eosc.IWorker 接口


type IWorker interface {
   Id() string
   Start() error
   Reset(conf interface{}, workers map[RequireId]IWorker) error
   Stop() error
   CheckSkill(skill string) bool
}

当插件配置被修改时,将会调用 Reset 方法,重置执行器内置数据,当插件被删除时,将会调用 Stop 方法。

3. 实现 eosc.IFilter 接口


type IFilter interface {
   DoFilter(ctx EoContext, next IChain) (err error)
   Destroy()
}

该接口在转发流程中被调用,其中 DoFilter 方法执行插件主流程,Destory 方法则在插件被删除时,销毁实例。

由于插件有顺序,在实际调用时,会将插件编排成调用链,并通过 next.DoChain(ctx) 操作调用下一个插件,您可以自定义调用插件前的操作,即 Access阶段 ,也可以自定义调用插件后的操作,即 Proxy 阶段 。代码示例如下:


func (r *ResponseRewrite) DoFilter(ctx eocontext.EoContext, next eocontext.IChain) (err error) {
 return http_service.DoHttpFilter(r, ctx, next)
}

func (r *ResponseRewrite) DoHttpFilter(ctx http_service.IHttpContext, next eocontext.IChain) error {
 if next != nil {
  err := next.DoChain(ctx)
  if err != nil {
   log.Error(err)
  }
 }

 return r.rewrite(ctx)
}

func (r *ResponseRewrite) Destroy() {
 r.statusCode = 0
 r.body = ""
 r.headers = nil
 r.match = nil
}

定义工厂创建方法


func NewFactory() eosc.IExtenderDriverFactory {
 return drivers.NewFactory[Config](Create, Check)
}

func Create(id, name string, conf *Config, workers map[eosc.RequireId]eosc.IWorker) (eosc.IWorker, error) {
 err := conf.doCheck()
 if err != nil {
  return nil, err
 }

 //若body非空且需要base64转码
 if conf.Body != "" && conf.BodyBase64 {
  conf.Body, err = utils.B64DecodeString(conf.Body)
  if err != nil {
   return nil, err
  }
 }

 r := &ResponseRewrite{
  WorkerBase: drivers.Worker(id, name),
  statusCode: conf.StatusCode,
  body:       conf.Body,
  headers:    conf.Headers,
  match:      conf.Match,
 }

 return r, nil
}

结合上文代码,当插件新建时,插件工厂会调用 Create 方法和 Check 方法,Create 方法负责初始化插件执行器实例,Check 方法一般用来校验插件配置的合法性,Check 方法用户可以按需实现,但 Create 方法必须实现。

定义工厂注册方法


const (
 Name = "response_rewrite"
)

func Register(register eosc.IExtenderDriverRegister) {
 register.RegisterExtenderDriver(Name, NewFactory())
}

将插件注册到拓展驱动管理器中

文件名:app/apinto/worker.go

 

使用插件

开发完成后,新插件就会被同步到节点插件中。我们可以在控制台界面 基础设施 > 节点插件新建插件

 

 新建插件时选择 eolinker.com:apinto:{插件名},本次演示的插件名为 response_rewrite,因此选择插件 eolinker.com:apinto:response_rewrite

若想了解插件的详细使用教程,可点击链接。

写在最后

本文简单介绍了插件入门相关细节,使用者可以根据业务需要,自行开发、安装/卸载、开启/关闭、编排插件,丰富网关能力,强化网关功能。

未来我们计划支持多语言插件,引入插件市场,个人开发者/企业可以将开发的插件贡献到插件市场中,与 Apinto 社区的使用者共享,合作共赢。

 

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

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

相关文章

《HeadFirst设计模式(第二版)》第十一章代码——代理模式

代码文件目录: RMI: MyRemote package Chapter11_ProxyPattern.RMI;import java.rmi.Remote; import java.rmi.RemoteException;public interface MyRemote extends Remote {public String sayHello() throws RemoteException; }MyRemoteClient packa…

Aurora 8B/10B

目录 1. Overview2. Feature List2. Block Diagram3. PDU Transmission Procedure3.1. User InterfaceFraming InterfaceStreaming Interface 3.2. Clock Compensation3.3. Aurora 8B/10B Frame Gen3.4. 8B/10B Transmission Code 4. PDU Reception Procedure5. Flow Control5.…

构建 NodeJS 影院微服务并使用 docker 部署【01/4】

图片来自谷歌 — 封面由我制作 一、说明 构建一个微服务的电影网站,需要Docker、NodeJS、MongoDB,这样的案例您见过吗?如果对此有兴趣,您就继续往下看吧。 在本系列中,我们将构建一个 NodeJS 微服务,并使用…

React2023电商项目实战 - 1.项目搭建

古人学问无遗力,少壮工夫老始成。 纸上得来终觉浅,绝知此事要躬行。 —— 陆游《《冬夜读书示子聿》》 系列文章目录 项目搭建App登录及网关App文章自媒体平台(博主后台)内容审核(自动) 文章目录 系列文章目录一、项目介绍1.页面…

使用@antv/x6-vue-shape 遇到的问题

最近用antv/x6开发一个功能,遇到的坑太多了,心累啊。。。 想用官方提供的antv/x6-vue-shape ,目的是使用vue组件创建画布元素。 官方文档: 链接:使用 HTML/React/Vue/Angular 渲染 | X6 使用npm install 安装 报错…

linux部署kafka3.5.1(单机)

一、下载jdk17 kafka3.x版本需要jdk11以上版本才能更好的兼容,jdk11、jdk17都是LTS长期维护版本,而且jdk17支持springboot3.x,所以我选择了openjdk17。 下载地址: Archived OpenJDK GA Releaseshttps://jdk.java.net/archive/ 二、上传jdk安装包解压 …

接口自动化yaml文件读取与写入

前言 在走进yaml文件之前大家应该都很想知道他是用来干嘛的? 是的是的,他是用来做接口自动化测试的。 我们一起来学习他吧!——(一定要收藏带走哦❤) 1、yaml文件有什么作用呢? ①可作为配置文件使用—…

linux tomcat server.xml 项目访问路径变更不生效

如果想改成默认的127.0.0.1:8080 访问项目 先确定更改的作用文件 server.xml 的 host:appBase 标签 默认找到appBase webapps 下的war包,并解压,解压后的appname为访问路径 也就变成了 127.0.0.1:8080/appname host:Context:path 标签 appBase的 优先…

HTTP 握手过程

HTTP 握手过程 TCP 建立连接 3 次握手 客户端请求连接服务器服务器响应成功客户端回应服务器准备开始连接 TCP 结束连接 4 次挥手 客户端向服务器发送,断开请求服务器向客户端发送,还有数据没有传输完毕,请稍等服务器向客户端发送&#x…

STM32L151C8T6 芯片数据手册

1. 芯片型号含义 2. Flash: 64KB 3. keil 配置ST-Link 烧录程序 4. keil 选择Flash 烧录算法 5. 系统主频 32Mhz 6. 时钟树 clock tree

《游戏编程模式》学习笔记(五)原型模式 Prototype Pattern

原型的定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 举个例子 假设我现在要做一款游戏,这个游戏里有许多不同种类的怪物,鬼魂,恶魔和巫师。这些怪物通过“生产者”进入这片区域,每种敌人…

Redis是如何保证高可用的?

Redis这种基于内存的关系型数据库我们在选用的时候就是考虑到它的快。而且可以很方便的实现诸如分布式锁、消息队列等功能。 笔者在前一段秋招面试的时候就被提问,“Redis是怎么保证高可用的?” 后续的子问题包含,集群模式是怎么实现的&…

基于docker搭建owncloud Harbor 构建镜像

环境介绍:ContenOS7.9 docker17.12.1-ce 使用mysql:5.6和 owncloud 镜像,构建一个个人网盘。 docker pull owncloud #拉取镜像 docker pull mysql5.6 创建容器 docker run --name owncloud-mysql -p 3306:3306 -e MYSQL\_ROOT\_PASSWORDroot …

leetcode303. 区域和检索 - 数组不可变(java)

前缀和数组的应用 区域和检索 - 数组不可变题目描述前缀和数组代码演示 区域和检索 - 数组不可变 难度 - 简单 原题链接 - 区域和检索 - 数组不可变 题目描述 给定一个整数数组 nums,处理以下类型的多个查询: 计算索引 left 和 right (包含 left 和 righ…

五种网络IO模型

五种模型出自:RFC标准。可参考: 《UNIX网络编程-卷一》 6.2 很多程序员是从高级语言的网络编程/文件操作了解到nio,继而了解到五种io模型的; 这五种io模型不止用于网络io “阻塞与****系统调用”是怎么回事?我知道了线…

简单认识镜像底层原理详解和基于Docker file创建镜像

文章目录 一、镜像底层原理1.联合文件系统(UnionFS)2.镜像加载原理3.为什么Docker里的centos的大小才200M? 二、Dockerfile1.简介2.Dockerfile操作常用命令 三、创建Docker镜像1.基于已有镜像创建2.基于本地模板创建3.基于Dockerfile创建4.Dockerfile多阶段构建镜像 一、镜像底…

Unity Android 之 使用 HanLP 进行句子段落的分词处理(包括词的属性处理)的简单整理

Unity Android 之 使用 HanLP 进行句子段落的分词处理(包括词的属性处理)的简单整理 目录 Unity Android 之 使用 HanLP 进行句子段落的分词处理(包括词的属性处理)的简单整理 一、简单介绍 二、实现原理 三、注意事项 四、效…

课程项目设计--项目建立--宿舍管理系统--springboot后端

前要 项目设计–宿舍管理系统 文章目录 项目建立导入依赖配置文件配置目录结构config配置mybatis-plusswagger 生成实体、mapper和servicebaseEntity统一响应实例响应码接口响应码接口实现统一响应result统一分页响应 项目建立 太长了,修改一下 导入依赖 暂时先加…

echarts 饼图 值为0时页面显示undefined%的解决方案

当饼图的数据为0时,页面会出现 undefined% 的情况 值为0的数据: pieData: [{name: 分类一,value: 0,},{name: 分类二,value: 0,}, ], //饼图数据 页面显示为undefined% 我们可以通过 label 的 formatter 来进行自定义调整,具体点就是在 fo…

蓝海创意云×悦乐兔99艺术节直播首秀顺利开播

8月18日,苏州悦乐兔99艺术节直播首秀顺利开播,蓝海创意云为此次直播提供了全程技术支持,使用自主研发的vLive虚拟直播系统嵌入整个直播流程,带给观众一场不一样的全新视觉体验。 蓝海创意云x悦乐兔直播首秀顺利开播 蓝海创意云助力…