Java程序员学习Go开发Higress的WASM插件

Java程序员学习Go开发Higress的WASM插件

契机

⚙ 今年天池大赛有higress相关挑战,研究一下。之前没搞过go,踩了很多坑,最主要的就是tinygo打包,多方寻求解决无果,结论是tinygo@0.32+go@1.19无法在macos arm架构下打包。升级go@1.21再次打包提示unsafe.SliceData requires go1.20 or later。后放弃macos+arm,采用ubuntu+amd64打包,ubuntu打包也必须使用tinygo@0.28.1。0.32.0在ubuntu仍然提示unsupported GOOS/GOARCH pair wasip1/wasm

环境布置

  • 包安装等可能需要依赖魔法,实在不行再配置代理仓库吧
  • 下载GoLand
  • 使用GoLand拷贝代码https://github.com/alibaba/higress
  • 定位到higress/plugins/wasm-go/extensions目录
  • 安装Golang1.19,推荐直接在IDE中安装
    • 访问这个地方https://go.dev/dl/找安装包
    • macos下载好的安装文件直接安装,默认会安装到/usr/local/go目录
  • TinyGo(要求 0.28.1 版本以上)安装
    • 官方指引链接:https://tinygo.org/getting-started/install/
    • macos直接brew install
      • brew tap tinygo-org/tools
      • brew install tinygo
      • 报错You are using macOS 15…(刚升级15系统
    • 下载安装https://tinygo.org/getting-started/install/macos/
      • tar xvzf tinygo0.32.0.darwin-amd64.tar.gz
      • 添加环境变量
        • vim ~/.bash_profile
        • 添加一行export PATH=<extract location>/tinygo/bin:$PATH
        • source ~/.bash_profile

官方Demo

  • 用GoLand打开higress,找到/plugins/wasm-go/extensions/hello-world
  • 使用master分支
  • 当前24年6月25日19点,我使用的Revision版本:ef4a0243aceb59ad0e630c40683c429a4f1198a0
  • 参考https://higress.io/zh-cn/docs/user/wasm-go/#2-编写-maingo-文件,把hello-world改造下顺便学习下语法
package main

import (
	"github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
	"github.com/higress-group/proxy-wasm-go-sdk/proxywasm"
	"github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types"
	"github.com/tidwall/gjson"
)

func main() {
	wrapper.SetCtx(
		// 插件名称
		"hello-world",
		// 为解析插件配置,设置自定义函数
		wrapper.ParseConfigBy(parseConfig),
		// 为处理请求头,设置自定义函数
		wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders),
	)
}

// MyConfig /*
type MyConfig struct {
	mockEnable bool
}

/*
在控制台插件配置中填写的yaml配置会自动转换为json,此处直接从json这个参数里解析配置即可
@note:
  - 星号表示指针
  - 传递一个指针给函数时,函数可以直接修改指针所指向的变量的值
*/
func parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {
	// 解析出配置,更新到config中
	config.mockEnable = json.Get("mockEnable").Bool()
	log.Info("yml配置此时为:" + json.Raw)
	return nil
}

/*
HTTP 请求头处理阶段,网关接收到客户端发送来的请求头数据时,触发wrapper.ProcessRequestHeadersBy
@note
  - 没有星号,表示副本,对副本的任意修改都不会影响到原来的变脸
*/
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
	log.Info("开始拦截header")
	//proxywasm工具类直接增加header
	err := proxywasm.AddHttpRequestHeader("hello", "world")
	if err != nil {
		return 0
	}
	//如果配置为的true,直接返回hello-world
	if config.mockEnable {
		//proxywasm工具类直接拦截返回response
		err := proxywasm.SendHttpResponse(200, nil, []byte("hello world"), -1)
		if err != nil {
			return 0
		}
	}
	return types.ActionContinue
}

在GoLand中,直接在方法中使用json gjson,会自动在go.mod和main.go的require中增加相关的依赖

higress插件可以实现的4个钩子

  • HTTP 请求头处理阶段:wrapper.ProcessRequestHeadersBy
  • HTTP 请求 Body 处理阶段:wrapper.ProcessRequestBodyBy
  • HTTP 应答头处理阶段:wrapper.ProcessResponseHeadersBy
  • HTTP 应答 Body 处理阶段:wrapper.ProcessResponseBodyBy

proxywasm工具类可以实现的方法如下

分类方法名称用途可以生效的HTTP 处理阶段
请求头处理GetHttpRequestHeaders获取客户端请求的全部请求头HTTP 请求头处理阶段
ReplaceHttpRequestHeaders替换客户端请求的全部请求头HTTP 请求头处理阶段
GetHttpRequestHeader获取客户端请求的指定请求头HTTP 请求头处理阶段
RemoveHttpRequestHeader移除客户端请求的指定请求头HTTP 请求头处理阶段
ReplaceHttpRequestHeader替换客户端请求的指定请求头HTTP 请求头处理阶段
AddHttpRequestHeader新增一个客户端请求头HTTP 请求头处理阶段
请求 Body 处理GetHttpRequestBody获取客户端请求 BodyHTTP 请求 Body 处理阶段
AppendHttpRequestBody将指定的字节串附加到客户端请求 Body 末尾HTTP 请求 Body 处理阶段
PrependHttpRequestBody将指定的字节串附加到客户端请求 Body 的开头HTTP 请求 Body 处理阶段
ReplaceHttpRequestBody替换客户端请求 BodyHTTP 请求 Body 处理阶段
应答头处理GetHttpResponseHeaders获取后端响应的全部应答头HTTP 应答头处理阶段
ReplaceHttpResponseHeaders替换后端响应的全部应答头HTTP 应答头处理阶段
GetHttpResponseHeader获取后端响应的指定应答头HTTP 应答头处理阶段
RemoveHttpResponseHeader移除后端响应的指定应答头HTTP 应答头处理阶段
ReplaceHttpResponseHeader替换后端响应的指定应答头HTTP 应答头处理阶段
AddHttpResponseHeader新增一个后端响应头HTTP 应答头处理阶段
应答 Body 处理GetHttpResponseBody获取客户端请求 BodyHTTP 应答 Body 处理阶段
AppendHttpResponseBody将指定的字节串附加到后端响应 Body 末尾HTTP 应答 Body 处理阶段
PrependHttpResponseBody将指定的字节串附加到后端响应 Body 的开头HTTP 应答 Body 处理阶段
ReplaceHttpResponseBody替换后端响应 BodyHTTP 应答 Body 处理阶段
HTTP 调用DispatchHttpCall发送一个 HTTP 请求-
GetHttpCallResponseHeaders获取 DispatchHttpCall 请求响应的应答头-
GetHttpCallResponseBody获取 DispatchHttpCall 请求响应的应答 Body-
GetHttpCallResponseTrailers获取 DispatchHttpCall 请求响应的应答 Trailer-
直接响应SendHttpResponse直接返回一个特定的 HTTP 应答-
流程恢复ResumeHttpRequest恢复先前被暂停的请求处理流程-
ResumeHttpResponse恢复先前被暂停的应答处理流程-

编译生成WASM文件

#整理下代码依赖啥的
go mod tidy
#进入插件目录
cd /higress/plugins/wasm-go/extensions/hello-world

#macos打包
/Users/y/GolandProjects/higress/plugins/wasm-go/extensions/hello-world
tinygo build -o main.wasm -scheduler=none -target=wasi -gc=custom -tags="custommalloc nottinygc_finalizer" ./
#提示异常
go: unsupported GOOS/GOARCH pair wasip1/wasm
#升级到go version go1.21.10 darwin/arm64
#打包提示:/Users/y/go/go1.21.10/src/strings/builder.go:49:23: unsafe.SliceData requires go1.20 or later
#todo 多方寻求解决无果,结论是无法在macos arm架构下打包
#todo tinygo只有31版本后才支持darwin,但是插件打包必须是28.1的tinygo

#找了ubuntu打包
#必须是这个tinygo版本,31版本任然提示go1.21.10
wget https://github.com/tinygo-org/tinygo/releases/download/v0.28.1/tinygo_0.28.1_amd64.deb
sudo dpkg -i tinygo_0.28.1_amd64.deb
wget https://go.dev/dl/go1.19.linux-amd64.tar.gz
tar  -xzf go1.19.linux-amd64.tar.gz
#找个profile放入下面环境变量source一下
export PATH=/home/go/bin:$PATH

#unbuntu初始化工程
mkdir /home/go_project_4_compile
cd /home/go_project_4_compile
go mod init wasm-demo-go
#代码复制上去
#整理依赖
go mod tidy
#再打包
tinygo build -o main.wasm -scheduler=none -target=wasi -gc=custom -tags="custommalloc nottinygc_finalizer" ./
#输出main.wasm,下载到本地

本地调试

#创建目录
mkdir ~/higress-plugin-hello
vim docker-compose.yaml
vim envoy.yaml
docker compose up

docker-compose.yaml

version: '3.7'
services:
  envoy:
    image: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/gateway:v1.4.0-rc.1
    entrypoint: /usr/local/bin/envoy
    # 注意这里对wasm开启了debug级别日志,正式部署时则默认info级别
    command: -c /etc/envoy/envoy.yaml --component-log-level wasm:debug
    depends_on:
    - httpbin
    networks:
    - wasmtest
    ports:
    - "10000:10000"
    volumes:
    - ./envoy.yaml:/etc/envoy/envoy.yaml
    - ./main.wasm:/etc/envoy/main.wasm

  httpbin:
    image: kennethreitz/httpbin:latest
    networks:
    - wasmtest
    ports:
    - "12345:80"

networks:
  wasmtest: {}

admin:
  address:
    socket_address:
      protocol: TCP
      address: 0.0.0.0
      port_value: 9901
static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          scheme_header_transformation:
            scheme_to_overwrite: https
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: httpbin
          http_filters:
          - name: wasmdemo
            typed_config:
              "@type": type.googleapis.com/udpa.type.v1.TypedStruct
              type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
              value:
                config:
                  name: wasmdemo
                  vm_config:
                    runtime: envoy.wasm.runtime.v8
                    code:
                      local:
                        filename: /etc/envoy/main.wasm
                  configuration:
                    "@type": "type.googleapis.com/google.protobuf.StringValue"
                    value: |
                      {
                        "mockEnable": false
                      }
          - name: envoy.filters.http.router
  clusters:
  - name: httpbin
    connect_timeout: 30s
    type: LOGICAL_DNS
    # Comment out the following line to test on v6 networks
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: httpbin
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: httpbin
                port_value: 80

验证

#10000为网关端口

#发送请求
curl -X GET -d '{"args":{},"headers":{"Accept":"*/*","Hello":"world","Host":"127.0.0.1:10000","Original-Host":"127.0.0.1:10000","Req-Start-Time":"1681269273896","User-Agent":"curl/7.79.1","X-Envoy-Expected-Rq-Timeout-Ms":"15000"},"origin":"172.18.0.3","url":"https://127.0.0.1:10000/get"}' http://127.0.0.1:10000/get 

返回
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Content-Length": "272",
    "Content-Type": "application/x-www-form-urlencoded",
    "Hello": "world",
    "Host": "127.0.0.1:10000",
    "Original-Host": "127.0.0.1:10000",
    "Req-Start-Time": "1719377044522",
    "User-Agent": "curl/8.7.1",
    "X-Envoy-Expected-Rq-Timeout-Ms": "15000"
  },
  "origin": "172.22.0.3",
  "url": "https://127.0.0.1:10000/get"
}

#修改本地的envoy.yaml
#将mockEnable配置修改为true

#重启下higress容器
curl -X GET -d '{"args":{},"headers":{"Accept":"*/*","Hello":"world","Host":"127.0.0.1:10000","Original-Host":"127.0.0.1:10000","Req-Start-Time":"1681269273896","User-Agent":"curl/7.79.1","X-Envoy-Expected-Rq-Timeout-Ms":"15000"},"origin":"172.18.0.3","url":"https://127.0.0.1:10000/get"}' http://127.0.0.1:10000/get

返回的
hello world

#日志也没问题
[2024-06-26 04:49:29.857][29][info][wasm] [external/envoy/source/extensions/common/wasm/context.cc:1311] wasm log wasmdemo: [hello-world] 开始拦截header
[2024-06-26 04:49:18.080][29][info][wasm] [external/envoy/source/extensions/common/wasm/context.cc:1311] wasm log: [hello-world] yml配置此时为:{
   "mockEnable": true
 }

总结

tinygo@0.32+go@1.19无法在macos arm架构下打包。升级go@1.21再次打包提示unsafe.SliceData requires go1.20 or later。后放弃macos+arm,采用ubuntu+amd64打包,ubuntu打包也必须使用tinygo@0.28.1。0.32.0在ubuntu仍然提示unsupported GOOS/GOARCH pair wasip1/wasm

写到最后

请添加图片描述

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

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

相关文章

【微服务】Alibaba Cloud Linux环境下Docker以及MySQL安装

部署Docker 1.安装dnf dnf是新一代的rpm软件包管理器 yum -y install dnf2.安装社区版Docker&#xff08;docker-ce&#xff09; 添加docker-ce的dnf源 dnf config-manager --add-repohttps://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo安装Alibaba Cloud…

从灵感到实践:Kimi辅助完成学术论文选题的文艺之旅

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 昨天我们为大家介绍了ChatGPT辅助完成实现设计&#xff08;AI与学术的交响&#xff1a;ChatGPT辅助下的实验设计新篇章&#xff09;。今天我们再来看看Kimi对于论文选题都能提供哪些帮助…

kali/ubuntu安装vulhub

无须更换源&#xff0c;安装docker-compose apt install docker.io docker -vdocker-compose #提示没有&#xff0c;输入y安装mkdir -p /etc/docker vi /etc/docker/daemon.json #更换dockerhub国内源┌──(root㉿kali)-[/home/kali/vulhub-master/tomcat/CVE-2017-12615] …

轻量级模型,重量级性能,TinyLlama、LiteLlama小模型火起来了

小身板&#xff0c;大能量。 当大家都在研究大模型&#xff08;LLM&#xff09;参数规模达到百亿甚至千亿级别的同时&#xff0c;小巧且兼具高性能的小模型开始受到研究者的关注。 小模型在边缘设备上有着广泛的应用&#xff0c;如智能手机、物联网设备和嵌入式系统&#xff0…

【数据分析】1、用Pandas计算数据相关性系数

相关性系数和相关分析是了解变量之间关系的重要工具。通过合理选择相关性系数和科学分析数据&#xff0c;能够有效揭示变量之间的关系&#xff0c;为进一步研究和决策提供有力支持。在实际应用中&#xff0c;应结合业务背景、数据特性和统计原则&#xff0c;谨慎解释和应用相关…

Pythonnet能导入clr,但无法引入System模块?

【pythonnet详解】—— Python 和 .NET 互操作的库_pythonnet 详细使用-CSDN博客 Python中动态调用C#的dll动态链接库中方法_python 如何调用c# dll-CSDN博客 需求&#xff1a;Python调用并传List<float>类型参数给.Net 起初&#xff1a;直接 # 创建一个Python浮点数…

ElasticSearch 和 MySQL的区别

MySQLElasticSearch 数据库&#xff08;database&#xff09;索引&#xff08;index&#xff09;数据表&#xff08;table&#xff09; 类型&#xff08;type&#xff09; 记录文档&#xff08;document&#xff0c;json格式&#xff09; 一、ES基础命令 1. ES cat查询命令 2.…

keil软件的一些使用技巧

1.MDK 的 TAB 键支持块操作 也就是可以让一片代码整体右移固定的几个位&#xff0c;也可以通过 SHIFTTAB 键整体左移固定的几个位。 2.快速注释与快速消注释 就是先选中你要注释的代码区&#xff0c;然后右键&#xff0c;选择Advanced→Comment Selection 就可以了。 3.快速打…

vue-cli搭建过程

1.vue-cli 概述 vue-cli 官方提供的一个脚手架&#xff0c;用于快速生成一个 vue 的项目模板&#xff0c;预先定义好的目录结构及基础代码 举个例子吧&#xff01; 比如之前学过的Maven,在创建 Maven 项目时可以选择创建一个骨架项目&#xff0c;这个骨架项目就是脚手架&#x…

web安全渗透测试十大常规项(一):web渗透测试之Fastjson反序列化

渗透测试之Java反序列化 1. Fastjson反序列化1.1 FastJson反序列化链知识点1.2 FastJson反序列化链分析1.3.1 FastJson 1.2.24 利用链分析1.3.2 FastJson 1.2.25-1.2.47 CC链分析1.3.2.1、开启autoTypeSupport:1.2.25-1.2.411.3.2.2 fastjson-1.2.42 版本绕过1.3.2.3 fastjson…

详解ApplicationRunner和CommandLineRunner

一、前言 springBoot框架项目&#xff0c;有时候有预加载数据需求——提前加载到缓存中或类的属性中&#xff0c;并且希望执行操作的时间是在容器启动末尾时间执行操作。比如笔者工作中遇到了一个预加载redis中的缓存数据&#xff0c;加载为java对象。针对这种场景&#xff0c…

15秒下雨短视频:成都柏煜文化传媒有限公司

15秒下雨短视频&#xff1a;瞬间的诗意与情感共鸣 在数字时代的浪潮中&#xff0c;短视频以其独特的魅力&#xff0c;成为了人们生活中不可或缺的一部分。其中&#xff0c;一段仅15秒的下雨短视频&#xff0c;成都柏煜文化传媒有限公司 或许在时间长河中只是一瞬间&#xff0c…

用通俗易懂方式讲解:快速部署大模型 ChatGLM3 并进行推理

在深入了解了一些大模型的知识之后&#xff0c;最好的方法是亲自动手搭建一个开源的大模型&#xff0c;以更深入地理解其工作原理。 在此基础上&#xff0c;我们将以 ChatGLM3 为例进行部署及推理&#xff0c;从而进一步探索大模型的应用和实践。 ChatGLM3简介&#xff1a; …

2024年度总结:不可错过的隧道IP网站评估推荐

随着网络技术的飞速发展&#xff0c;隧道IP服务成为了许多企业和个人在进行网络活动时的得力助手。作为专业的测评团队&#xff0c;我们经过一整年的深入研究和测试&#xff0c;为大家带来了三款备受瞩目的隧道IP网站推荐——品易HTTP、极光HTTP和一G代理。接下来&#xff0c;我…

智慧校园-教材管理系统总体概述

智慧校园教材管理系统&#xff0c;作为教育信息化进程的又一实践成果&#xff0c;正逐步改变着传统教材管理的模式。该系统通过集成先进的信息技术&#xff0c;对教材从采购、分配、使用到回收的全过程进行了全面的数字化改造&#xff0c;旨在构建一个高效、透明、节约的教材管…

Python生成和识别二维码教程

引言 二维码&#xff08;QR Code&#xff09;在日常生活中非常常见&#xff0c;广泛应用于支付、登录验证、信息分享等场景。本文将介绍如何使用Python生成和识别二维码&#xff0c;适合初学者快速上手。我们将使用qrcode和pyzbar库来实现这一功能。 环境准备 在开始之前&am…

IT项目管理中如何沟通?

IT项目管理中的沟通是保证项目顺利进行的关键。以下是一些创意文案&#xff0c;用以强调和展示在IT项目管理中进行有效沟通的策略和重要性&#xff1a; 代码与文化的编织者&#xff1a;在IT项目管理中&#xff0c;沟通不仅需要技术的精准&#xff0c;更需要文化的融合&#xff…

Qt中用QLabel创建状态灯

首先ui设计中分别创建了4个大灯和4个小灯。 编辑.h文件 #ifndef LED_H #define LED_H#include <QWidget> #include <QLabel>QT_BEGIN_NAMESPACE namespace Ui { class Led; } QT_END_NAMESPACEclass Led : public QWidget {Q_OBJECTpublic:Led(QWidget *parent n…

苹果电脑文件清理软件哪个好 苹果电脑如何清理内存和垃圾文件 cleanMyMac X 4.8.0激活号码

苹果电脑一直以其出色的性能和优雅的设计吸引着无数忠实用户。然而&#xff0c;众所周知&#xff0c;随着时间的推移和使用的增加&#xff0c;您的Mac可能会开始变慢&#xff0c;就像任何高性能设备&#xff0c;长时间使用后总会积累些“灰尘”。但在苹果电脑上就不是真的灰尘哦…

Vite:打包时去除console

需求描述 在生产环境下&#xff0c;Vite打包项目时&#xff0c;需要去除开发时加入的console、debugger调试信息&#xff0c;但是又不想引入terser。 解决方案 esbuild 参考&#xff1a; esbuild - API 修改配置 修改vite.config.js配置文件&#xff0c;新增配置项如下&…