higress-demo's Introduction
higress-demo's People
higress-demo's Issues
Error occured while calling redis, it seems cannot find the redis cluster.
测试的 redis call plugin。
前提:同一台测试服务器上,docker-compose 部署了 higress 1.4.0, 非docker的方式起了 redis 二进制文件。
配置:
1. 服务来源配置
2. 插件配置
镜像地址: oci://registry.cn-hangzhou.aliyuncs.com/lindaman/redis-plugin:1.1.0
3. 域名配置,见下方的《nacos插件配置》
问题描述:在进行《插件配置》操作时, redis 能正常 get、 set;然后测试域名配置,就会报错 “Error occured while calling redis, it seems cannot find the redis cluster.”。
错误详日志如下
[Envoy (Epoch 0)] [2024-06-20 14:37:38.304][484][error][wasm] wasm log: [redis-demo] init redis client success [Envoy (Epoch 0)] [2024-06-20 14:37:38.304][484][error][wasm] wasm log: [redis-demo] redis client set success [Envoy (Epoch 0)] [2024-06-20 14:37:38.304][484][error][wasm] wasm log: [redis-demo] init redis client success [Envoy (Epoch 0)] [2024-06-20 14:37:38.305][484][error][wasm] wasm log: [redis-demo] init redis client success [Envoy (Epoch 0)] [2024-06-20 14:37:38.305][495][error][wasm] wasm log: [redis-demo] print redis client set reponse OK [Envoy (Epoch 0)] [2024-06-20 14:37:38.305][495][error][wasm] wasm log: [redis-demo] print redis client get reponse pax [Envoy (Epoch 0)] [2024-06-20 14:37:38.305][484][error][wasm] wasm log: [redis-demo] redis client set success [Envoy (Epoch 0)] [2024-06-20 14:37:38.305][484][error][wasm] wasm log: [redis-demo] init redis client success [Envoy (Epoch 0)] [2024-06-20 14:37:38.305][484][critical][wasm] wasm log: Error occured while calling redis, it seems cannot connect to the redis cluster. request-id:ea3d0929-3e7a-4f23-8b69-3f1069272f5f [Envoy (Epoch 0)] [2024-06-20 14:37:38.306][484][error][wasm] wasm log: [redis-demo] redis client set failed [Envoy (Epoch 0)] [2024-06-20 14:37:38.306][484][critical][wasm] wasm log: Error occured while calling redis, it seems cannot connect to the redis cluster. request-id:01a3d4f8-9227-4006-853d-e3f89b3de8ad
nacos 插件配置如下:
apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
annotations:
higress.io/wasm-plugin-description: redis 测试插件
higress.io/wasm-plugin-title: redis-plugin
creationTimestamp: null
labels:
higress.io/resource-definer: higress
higress.io/wasm-plugin-built-in: "false"
higress.io/wasm-plugin-category: custom
higress.io/wasm-plugin-name: redis-plugin
higress.io/wasm-plugin-version: 1.0.0
managedFields:
- apiVersion: extensions.higress.io/v1alpha1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:higress.io/wasm-plugin-description: {}
f:higress.io/wasm-plugin-title: {}
f:labels:
.: {}
f:higress.io/resource-definer: {}
f:higress.io/wasm-plugin-built-in: {}
f:higress.io/wasm-plugin-category: {}
f:higress.io/wasm-plugin-name: {}
f:higress.io/wasm-plugin-version: {}
f:spec:
f:defaultConfig:
.: {}
f:qpm: {}
f:serviceName: {}
f:timeout: {}
f:matchRules: {}
f:priority: {}
f:url: {}
manager: Kubernetes Java Client
operation: Update
time: "2024-06-20T14:33:42Z"
name: redis-plugin-1.0.0
namespace: higress-system
spec:
defaultConfig:
qpm: 2
serviceName: local-redis.static
timeout: 10000
matchRules:
- config:
qpm: 1
serviceName: local-redis.static
timeout: 10000
configDisable: true
ingress:
- gaia-demo
- config:
qpm: 2
serviceName: local-redis.static
timeout: 10000
domain:
- arch-ad-management-test-1.xxx.net
priority: "1"
url: oci://registry.cn-hangzhou.aliyuncs.com/lindaman/redis-plugin:1.0.9
status: {}
测试代码如下:
package main
import (
"fmt"
"strconv"
"strings"
"time"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types"
"github.com/tidwall/gjson"
"github.com/tidwall/resp"
"github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
)
func main() {
wrapper.SetCtx(
"redis-demo",
wrapper.ParseConfigBy(parseConfig),
wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders),
wrapper.ProcessResponseHeadersBy(onHttpResponseHeaders),
)
}
type RedisCallConfig struct {
client wrapper.RedisClient
qpm int
}
func parseConfig(json gjson.Result, config *RedisCallConfig, log wrapper.Log) error {
// 带服务类型的完整 FQDN 名称,例如 my-redis.dns、redis.my-ns.svc.cluster.local
serviceName := json.Get("serviceName").String()
servicePort := json.Get("servicePort").Int()
if servicePort == 0 {
if strings.HasSuffix(serviceName, ".static") {
// 静态IP类型服务的逻辑端口是80
servicePort = 80
} else {
servicePort = 6379
}
}
username := json.Get("username").String()
password := json.Get("password").String()
// 单位是毫秒
timeout := json.Get("timeout").Int()
if timeout == 0 {
timeout = 1000
}
qpm := json.Get("qpm").Int()
config.qpm = int(qpm)
config.client = wrapper.NewRedisClusterClient(wrapper.FQDNCluster{
FQDN: serviceName,
Port: servicePort,
})
err := config.client.Init(username, password, timeout)
if err != nil {
log.Errorf("init redis client failed")
} else {
log.Error("init redis client success")
err := config.client.Set("name", "pax", func(response resp.Value) {
if response.Error() != nil {
log.Errorf("redis client set failed")
} else {
log.Errorf("print redis client set reponse " + response.String())
}
})
if err != nil {
log.Errorf("redis client set failed")
} else {
log.Errorf("redis client set success")
config.client.Get("name", func(response resp.Value) {
if response.Error() != nil {
log.Errorf("redis client get failed")
} else {
log.Errorf("print redis client get reponse " + response.String())
}
})
}
log.Error("init redis client success")
}
return err
}
func onHttpRequestHeaders(ctx wrapper.HttpContext, config RedisCallConfig, log wrapper.Log) types.Action {
now := time.Now()
minuteAligned := now.Truncate(time.Minute)
timeStamp := strconv.FormatInt(minuteAligned.Unix(), 10)
// 如果 redis api 返回的 err != nil,一般是由于网关找不到 redis 后端服务,请检查是否误删除了 redis 后端服务
err := config.client.Incr(timeStamp, func(response resp.Value) {
if response.Error() != nil {
fmt.Println(response.Error())
log.Errorf("call redis error: %v", response.Error())
proxywasm.ResumeHttpRequest()
} else {
log.Errorf("start redis on http request headers")
ctx.SetContext("timeStamp", timeStamp)
ctx.SetContext("callTimeLeft", strconv.Itoa(config.qpm-response.Integer()))
if response.Integer() == 1 {
err := config.client.Expire(timeStamp, 60, func(response resp.Value) {
if response.Error() != nil {
log.Errorf("call redis error: %v", response.Error())
}
proxywasm.ResumeHttpRequest()
})
if err != nil {
fmt.Println(err.Error())
log.Errorf(err.Error())
log.Errorf("Error occured while calling redis, it seems cannot find the redis cluster.")
proxywasm.ResumeHttpRequest()
}
} else {
if response.Integer() > config.qpm {
proxywasm.SendHttpResponse(429, [][2]string{{"timeStamp", timeStamp}, {"callTimeLeft", "0"}}, []byte("Too many requests\n"), -1)
} else {
proxywasm.ResumeHttpRequest()
}
}
}
})
if err != nil {
fmt.Println(err.Error())
log.Errorf(err.Error())
// 由于调用redis失败,放行请求,记录日志
log.Errorf("Error occured while calling redis, it seems cannot find the redis cluster.")
return types.ActionContinue
} else {
// 请求hold住,等待redis调用完成
return types.ActionPause
}
}
func onHttpResponseHeaders(ctx wrapper.HttpContext, config RedisCallConfig, log wrapper.Log) types.Action {
if ctx.GetContext("timeStamp") != nil {
proxywasm.AddHttpResponseHeader("timeStamp", ctx.GetContext("timeStamp").(string))
}
if ctx.GetContext("callTimeLeft") != nil {
proxywasm.AddHttpResponseHeader("callTimeLeft", ctx.GetContext("callTimeLeft").(string))
}
return types.ActionContinue
}
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.