亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot如何通過redisTemplate調用lua腳本并打印調試信息到redislog

發布時間:2021-10-15 15:57:53 來源:億速云 閱讀:168 作者:柒染 欄目:編程語言

這篇文章將為大家詳細講解有關SpringBoot如何通過redisTemplate調用lua腳本并打印調試信息到redislog,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

第一次寫Lua腳本,并通過springboot的redisTemplate調用腳本,進行腳本與應用的交互。不熟悉真的折騰了好久,現在總結一下學習過程:

第一次寫完lua時,想到的就是如何在應用調用腳本的時候,去調試腳本。在網上海搜了一把,能找到的有點相關的寥寥無幾。

有一種方法是通過執行redis命令,調用redis客戶端,加載lua腳本,然后出現基于命令行調試的交互界面,輸入調試命令去調試腳本。如下:

在終端輸入命令:redis-cli.exe --ldb --eval LimitLoadTimes.lua 1 mykey , myargv

--ldb:redis-cli.exe進行命令調試的必要參數

--eval:告訴redis客戶端去加載Lua腳本,后面跟著的就是 lua腳本的路徑(我是直接放在redis目錄下),

1:傳給Lua腳本的key的數量,我測試的時候是1

--mykey:自己傳的一個key值,和前面的數量1對應

--myargv:自己傳的除key外的參數,可以是多個

注,命令中的逗號不能忽略,并且前后要有一個空格

回車,如上圖,本來以為可以進入調試,結果等了半天,一直沒有出現交互的命令行界面,找了好久,還是沒找到辦法,結果只好先暫停(如果有大神遇到這種情況,跪求解~~)。換一種調試方式,把調試信息打在redis日志上。

下面是我自己調用腳本時,打印調試信息的方式,如果有更好的方式,請不吝賜教。

1、選擇redisTemplate序列化方式

首先,創建一個redisTemplate,具體代碼就不說了,這個比較簡單。要注意的是,需要設置redisTemplate的序列化方式,springBoot默認是基于java jdk的序列化。通過這種序列化后的參數傳到Lua腳本是,是無法正常打印到redis日志的,會出現亂碼,而且參數如果傳的是一個Map或List的話,不方便解析。并且這種序列化占用的字節比較大。所以改成JSON序列化,用FastJson實現。

下面貼上redis序列化代碼:

public class FastJsonRedisSerializer<T> implements RedisSerializer<T> { public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); private Class<T> clazz; public FastJsonRedisSerializer(Class<T> clazz){  super();  this.clazz = clazz; } @Override public byte[] serialize(T t) throws SerializationException {  return ofNullable(t)    .map(r -> JSON.toJSONString(r, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET))    .orElseGet(() -> new byte[0]); } @Override public T deserialize(byte[] bytes) throws SerializationException {  return Optional.ofNullable(bytes)    .map(t -> JSON.parseObject(new String(t, DEFAULT_CHARSET), clazz))    .orElseGet(() -> null); }}

2、應用端加載腳本,并設置傳遞參數

在springboot中,是用 DefaultRedisScript 類來加載腳本的,并設置相應的數據類型來接收lua腳本返回的數據,這個泛型類在使用時設置泛型是什么類型,腳本返回的結果就是用什么類型接收。注意,該類只接收4種類型的返回類型,之前沒注意,還納悶為什么出錯,看源碼才曉得,截圖,如下:

在lua腳本中,有兩個全局的變量,是用來接收redis應用端傳遞的鍵值和其它參數的,分別為KEYS、ARGV。

在應用端傳遞給KEYS時是一個數組列表,在lua腳本中通過索引方式獲取數組內的值。

在應用端,傳遞給ARGV的參數比較靈活,可以是多個獨立的參數,但對應到Lua腳本中是,統一用ARGV這個數組接收,獲取方式也是通過數組下標獲取。

下面貼上應用端的測試代碼:

@Service("luaScriptService")public class LuaScriptServiceImpl implements LuaScriptService{ @Autowired private RedisTemplate<String,Object> redisTemplate1; private DefaultRedisScript<List> getRedisScript; @PostConstruct public void init(){  getRedisScript = new DefaultRedisScript<List>();  getRedisScript.setResultType(List.class);  getRedisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("luascript/LimitLoadTimes.lua"))); } @Override public void redisAddScriptExec(){  /**   * List設置lua的KEYS   */  List<String> keyList = new ArrayList();  keyList.add("count");  keyList.add("rate.limiting:127.0.0.1");  /**   * 用Mpa設置Lua的ARGV[1]   */  Map<String,Object> argvMap = new HashMap<String,Object>();  argvMap.put("expire",10000);  argvMap.put("times",10);  /**   * 調用腳本并執行   */  List result = redisTemplate1.execute(getRedisScript,keyList, argvMap);  System.out.println(result); }}

代碼中發送了兩個key,還有一個map包裝的argv,傳遞到Lua腳本中時,KEYS和ARGV接收到的是對象字符串,所以得用lua的庫做相關的解碼,我們發送的時候是用json序列化的,用Lua的庫cjson可以轉成json對象。下面貼上Lua腳本代碼:

--獲取KEYlocal key1 = KEYS[1]local key2 = KEYS[2]-- 獲取ARGV[1],這里對應到應用端是一個List<Map>.-- 注意,這里接收到是的字符串,所以需要用csjon庫解碼成table類型local receive_arg_json = cjson.decode(ARGV[1])--返回的變量local result = {}--打印日志到reids--注意,這里的打印日志級別,需要和redis.conf配置文件中的日志設置級別一致才行redis.log(redis.LOG_DEBUG,key1)redis.log(redis.LOG_DEBUG,key2)redis.log(redis.LOG_DEBUG, ARGV[1],#ARGV[1])--獲取ARGV內的參數并打印local expire = receive_arg_json.expirelocal times = receive_arg_json.timesredis.log(redis.LOG_DEBUG,tostring(times))redis.log(redis.LOG_DEBUG,tostring(expire))--往redis設置值redis.call("set",key1,times)redis.call("incr",key2)redis.call("expire",key2,expire)--用一個臨時變量來存放json,json是要放入要返回的數組中的local jsonRedisTemp={}jsonRedisTemp[key1] = redis.call("get",key1)jsonRedisTemp[key2] = redis.call("get", key2)jsonRedisTemp["ttl"] = redis.call("ttl",key2)redis.log(redis.LOG_DEBUG, cjson.encode(jsonRedisTemp))result[1] = cjson.encode(jsonRedisTemp) --springboot redistemplate接收的是List,如果返回的數組內容是json對象,需要將json對象轉成字符串,客戶端才能接收result[2] = ARGV[1] --將源參數內容一起返回redis.log(redis.LOG_DEBUG,cjson.encode(result)) --打印返回的數組結果,這里返回需要以字符返回return result

3、設置日志級別

代碼中,redis.log()函數向運日志中輸出信息,這里要注意一下,函數里面設置的日志級別要和redis.conf配置文件中設置的日志級別一樣才能正常打印到文件,這里我是設置成了deubg級別。這里可設置的級別有4種,分別如下:

redis.LOG_DEBUG  redis.LOG_VERBOSE  redis.LOG_NOTICE  redis.LOG_WARNING

在應用端,我們設置接收返回的數據類型是List,所以在Lua腳本中,返回的類型用table與之對應,并且放到table變量中的內容,得是字符串,應用端才能通過反序列化,正常解析。下圖是輸出lua返回值的打印信息:

至此,結束,希望也能對其遇到相同問題的朋友有所幫助。

關于SpringBoot如何通過redisTemplate調用lua腳本并打印調試信息到redislog就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

怀来县| 泾川县| 上思县| 柳林县| 萍乡市| 汪清县| 买车| 大埔区| 西峡县| 新竹市| 扬中市| 手游| 长春市| 垫江县| 婺源县| 松桃| 犍为县| 兴文县| 汝南县| SHOW| 永善县| 萨迦县| 仁怀市| 山丹县| 台北市| 平塘县| 南京市| 高邑县| 渝中区| 观塘区| 平邑县| 迁西县| 平乐县| 嫩江县| 阜城县| 晋宁县| 余姚市| 靖边县| 榆树市| 石棉县| 洛隆县|