Git Product home page Git Product logo

higress-demo's Introduction

higress-demo

higress-demo's People

Contributors

johnlanni avatar rinfx avatar weixinx avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

ch3cho rinfx weixinx

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. 服务来源配置
image
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 photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.