Code Monkey home page Code Monkey logo

lua-resty-etcd's Introduction

lua-resty-etcd's People

Contributors

chronolaw avatar doublespout avatar fengjx avatar gerrard-ynwa avatar gonego1ng avatar huntkalio avatar johzchen avatar leslie-tsang avatar membphis avatar moonming avatar nic-6443 avatar nic-chen avatar pigercc avatar shuaijinchao avatar sn0rt avatar spacewander avatar supermario1990 avatar tokers avatar tzssangglass avatar u5surf avatar willmafh avatar yiyiyimu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

lua-resty-etcd's Issues

feature: support `compact` for etcd v3

The length of keyspace is not limited to 1000 anymore in v3. To avoid performance degradation and eventual storage space exhaustion, operation compact could drop all information about keys superseded prior to a given keyspace revision. And the compacted ones could not be accessed by get or watch. Normally, there would be auto compaction when etcd is running.
Detail could be found here.

discuss: endpoint choose issue

Background

  1. Currently, lua-resty-etcd supports cluster mode, but the way of implementation is too simple: each connection changes to the next endpoint.

  2. Using this mechanism, it can work well under normal circumstances, but once an api or an instance has a problem, the consequences will be unpredictable.

Issues with the current solution

  1. In cluster mode, when an instance is down, there is no way to skip the down instance, and it will still be polled every time.

  2. When all instances of a certain api fail (such as auth api), it will cause crazy retries, which may eventually overwhelm the ETCD cluster.

Suggested changes

  1. Implement a health check mechanism, no active check is required, only passive check is required, that is, it is recorded when the connection fails.

  2. There is no need to poll all instances, and only switch instances when the connection fails.

  3. In a certain period of time, if there are n consecutive failures, the instance is considered unhealthy, and the instance will not be connected for a certain period of time in the future (the duration and times can be configured).

related issue: apache/apisix#2899

what do you think ?

Thanks.

feature: add lint check

Add lint-check in makefile and travis CI for better formatting.

Use the same linting strategy as APISIX.

Bug: If value is large, v3:watch will cause `json decode` error

If value is large, v3:watch will cause json decode error.

http chunk proctocol like this:
[chunk size][\r\n][chunk data][\r\n][chunk size][\r\n][chunk data][\r\n][chunk size = 0][\r\n][\r\n]

Raw http chunk package is like:

`
32
{some etcd data}

1 <------(here will cause bug)

64
{some etcd data}

0

`

image
if body is "\n", decode_json will caused error

https://github.com/api7/lua-resty-etcd/blob/master/lib/resty/etcd/v3.lua#L523

I will be fix this bug soon, and get a pull request

etcd v3 set timeout to 0 causing "can't resume a dead coroutine"

Hi there, when I use watch feature with etcd v3, unexpected error occurred when setting timeout to 0, which I need to keep watching the peers, any idea what I was missing?

my code
local func, err = _M.etcd:watch(key, { timeout = 0 -- forever watch })

log info
2021/02/04 12:08:50 [info] 10188#12103689: *5 [lua] v3.lua:518: request_chunk(): http request meth od: POST path: /v3/watch body: {"create_request":{"key":"c2VydmVy"}} query: nil, context: ngx.time r 2021/02/04 12:09:00 [error] 10188#12103689: *5 [lua] monitor.lua:28: watch_server(): timeout, context: ngx.timer 2021/02/04 12:09:00 [error] 10188#12103689: *5 lua coroutine: runtime error: .../local/Cellar/openresty/1.15.8.3_1/lualib/resty/http.lua:409: bad argument #1 to 'tonumber' (string expected, got nil) stack traceback: coroutine 0: [C]: in function 'tonumber' .../local/Cellar/openresty/1.15.8.3_1/lualib/resty/http.lua:409: in function <.../local/Cellar/openresty/1.15.8.3_1/lualib/resty/http.lua:383> coroutine 1: [C]: in function 'co_resume' .../local/Cellar/openresty/1.15.8.3_1/lualib/resty/http.lua:80: in function 'body_reader' ...cuments/projects/openresty//lua/vendor/resty/etcd/v3.lua:533: in function 'func' ...ents/projects/openresty//lua/goatkeeper/etcd/monitor.lua:25: in function 'watch_server' ...ents/projects/openresty//lua/goatkeeper/etcd/monitor.lua:84: in function 'watch_config' ...ments/projects/openresty//lua/goatkeeper/etcd/syncer.lua:66: in function <...ments/projects/openresty//lua/goatkeeper/etcd/syncer.lua:56>, context: ngx.timer 2021/02/04 12:09:00 [error] 10188#12103689: *5 [lua] monitor.lua:28: watch_server(): failed to dec ode json body: Expected value but found invalid token at character 1, context: ngx.timer 2021/02/04 12:09:00 [error] 10188#12103689: *5 [lua] monitor.lua:28: watch_server(): can't resume a dead coroutine, context: ngx.timer 2021/02/04 12:09:00 [error] 10188#12103689: *5 [lua] monitor.lua:28: watch_server(): can't resume a dead coroutine, context: ngx.timer 2021/02/04 12:09:00 [error] 10188#12103689: *5 [lua] monitor.lua:28: watch_server(): can't resume a dead coroutine, context: ngx.timer

bug: missing value field and got decode error while value is an empty string

reproduce step

  1. set empty string
etcdctl set /t/empty ''
  1. use etcd v2 client get and get body as below
{
    "node":{
        "nodes":[
            {
                "createdIndex":9,
                "key":"/t/empty",
                "modifiedIndex":9
            }
        ],
        "modifiedIndex":9,
        "createdIndex":9,
        "key":"/t",
        "dir":true
    },
    "action":"get"
}

also an error log from v2.lua

2020/08/11 22:15:44 [error] 8951#0: *2 [lua] v2.lua:274: decode_dir_value(): failed to decode json: Expected value but found T_END at character 1, context: ngx.timer

It seems that decode_dir_value didn't hand empty string properly.

After dive in the implement of v2.lua, does this lib only support for json string value?

"lua tcp socket read time out" keeps flushing and "worker is shutting down" after reloading

I'm trying to write a simple timer function to watch a specified key in etcd.
It seems that this funtion can work: When I change the value of key in etcd, it will get the changes as expected. But when there is no changes, "lua tcp socket read time out" keeps flushing in error.log.

After I execute openresty -s reload, the previous worker process will not exit and keep the status "worker process is shutting down" for a very long time (I even do not know if it will keep this status forever)

Here is part of the code (Sorry that I cannot handle the style well...):
watch.lua:
local function watch(premature, self)
if premature then
return
end
local opts = {}
opts["protocol"] = config["etcd"][env]["protocol"]
opts["http_host"] = config["etcd"][env]["http_host"]

local cli, callback, err
cli, err = etcd.new(opts)
if err then
    ngx.log(ngx.ERR, "new etcd err: " .. err)
    ngx.timer.at(5, watch, self)
    return
end
local attr = {}
attr["timeout"] = 3
callback, err = cli:watchdir(config["etcd"][env]["watch_prefix"], attr)
if err then
    ngx.log(ngx.ERR, "get key error")
    ngx.timer.at(5, watch, self)
    return
end
local created_true = callback()
local watch_res = callback()
if watch_res then
    ngx.log(ngx.INFO, serializeTable(watch_res))
end
ngx.sleep(0.5)
ngx.timer.at(0, watch, self)

end

nginx.conf:
init_worker_by_lua_block{
local w = require("watch");
w:init();
}

watchdir opts args type error

  • version: 0.8

  • v3.watchdir

opts: progress_notify, prev_kv, fragment type error and etcd api response: json: cannot unmarshal string into Go value of type bool

add log code and print

local chunk_fun, err = etcd_cli:watchdir("/watch/test", {timeout = 60, prev_kv = true, fragment = true})
if res.status >= 300 then
    ngx.log(ngx.ERR, "response: " .. res.body_reader());
    return nil, "failed to watch data, response code: " .. res.status
end
 [lua] v3.lua:502: request_chunk(): http request method: POST path: /v3/watch body: {"create_request":{"range_end":"L21pY3Jvcy9zZXJ2aWNm","fragment":"true","key":"L21pY3Jvcy9zZXJ2aWNl","prev_kv":"true"}} query: nil
 [lua] v3.lua:510: request_chunk(): response: {"error":"json: cannot unmarshal string into Go value of type bool","message":"json: cannot unmarshal string into Go value of type bool","code":2}

this should be bool, maybe protobuf can not convert 'true' / 'false' to a bool

-- v3.lua
local prev_kv
if attr.prev_kv then
    prev_kv = attr.prev_kv and 'true' or 'false'
    -- fix: prev_kv = attr.prev_kv and true or false
end

local progress_notify
if attr.progress_notify then
    progress_notify = attr.progress_notify and 'true' or 'false'
    -- fix: progress_notify = attr.progress_notify and true or false
end

local fragment
if attr.fragment then
    fragment = attr.fragment and 'true' or 'false'
    -- fix: fragment = attr.fragment and true or false
end

V3 doc mistake

image

    if protocol == "v3" then
        local sub_ver = ver.etcdserver:sub(1, 4)
        local etcd_prefix = prefix_v3[sub_ver] or "/v3beta"
        opts.api_prefix = etcd_prefix .. (opts.api_prefix or "")
        return etcdv3.new(opts)
    end

option.api_prefix not option.preifx

it happens time out per 1minute when use etcd v3 watch method

problem

when I use etcd v3 watch method(default params),The following questions occurs:

  1. it happens time out per 1minute .
  2. There is a lot of connection building with etcd server in per worker progress

log info:

2020/04/15 15:05:34 [info] 9020#9020: *20628390 [lua] v3.lua:502: request_chunk(): http request method: POST path: /v3beta/watch body: {"create_request":{"range_end":"*********","start_revision":6647555,"key":"L2V0Y2QvY2ZnL2dsb2JhbA=="}} query: nil, context: ngx.timer
2020/04/15 15:06:34 [info] 9020#9020: *20628390 [lua] v3.lua:502: request_chunk(): http request method: POST path: /v3beta/watch body: {"create_request":{"range_end":"*********","start_revision":6647555,"key":"L2V0Y2QvY2ZnL2dsb2JhbA=="}} query: nil, context: ngx.timer
2020/04/15 15:07:34 [info] 9020#9020: *20628390 [lua] v3.lua:502: request_chunk(): http request method: POST path: /v3beta/watch body: {"create_request":{"range_end":"*********","start_revision":6647555,"key":"L2V0Y2QvY2ZnL2dsb2JhbA=="}} query: nil, context: ngx.timer
2020/04/15 15:08:34 [info] 9020#9020: *20628390 [lua] v3.lua:502: request_chunk(): http request method: POST path: /v3beta/watch body: {"create_request":{"range_end":"*********","start_revision":6647555,"key":"L2V0Y2QvY2ZnL2dsb2JhbA=="}} query: nil, context: ngx.timer
.......

other info:

etcd endpoints has three ip list such as (1.1.1.1:2379;1.1.1.2:2379;1.1.1.3:2379;)

connection info:
such as worker id: 9020 exits 58 establish connection

root@****:~# netstat -apn|grep 2379 |grep 'ESTABLISHED 9020' |wc -l
58

@YuanSheng Wang Have you met this problem? How to solve

feature: support watch cancel

Since in etcd v3 watch would watch all changes before the timeout, compared to only watch the first change in etcd v2. Thus v3 also supports manually cancel the watch before the watch expires.

error when connect the etcd

2020/02/21 04:59:32 [error] 16028#16028: *181 [lua] v2.lua:337: get(): failed to json decode: Expected value but found invalid token at character 1, client: 192.168.0.105, server: localhost, request: "GET /gray HTTP/1.1", host: "192.168.0.107"

1 the set methd is ok

`
local cli, err = require("resty.etcd").new({prototol = "v2", http_host = "http://127.0.0.1:2379"})
local res, err = cli:get('/test/gray/123-456-789')

ngx.print('hello')
`

mark tag 1.3 is pathological

Since there is a bug in 1.3 which was fixed now, i think may be we need to mark that tag 1.3 is not safe to use and public the next release.

bug: https://travis-ci.org/iresty/lua-resty-etcd

t/key.t ........ 40/? 
#   Failed test 'TEST 7: wait(key) - response_body - response is expected (repeated req 1, req 0)'
#   at /usr/local/share/perl/5.22.1/Test/Nginx/Socket.pm line 1589.
# @@ -1,4 +1,4 @@
#  checked val as expect: abc
#  err: timeout, more than 1sec: true
#  checked val as expect: bcd
# -wait more than 1sec: true
# +wait more than 1sec: false

Dependency problem

Could you guys tell where local tab_nkeys = require "table.nkeys" is from ?

thanks

v3 doc need more example

v3 doc need more example, such as api return schema like:

  events = { {
      kv = {
        create_revision = "42",
        key = "/aaa/bbb",
        mod_revision = "43",
        value = "abc",
        version = "2"
      }
    }, {
      kv = {
        key = "/xxx/yyy",
        mod_revision = "44"
      },
      type = "DELETE"
    } },
  header = {
    cluster_id = "14841639068965178418",
    member_id = "10276657743932975437",
    raft_term = "2",
    revision = "44"
  }
}

Couldn't install lua-resty-etcd v0.8 via luarocks

When I try to install lua-resty-etcd using luarocks I get following error:

luarocks --local install lua-resty-etcd 0.8
Installing http://luarocks.org/repositories/rocks/lua-resty-etcd-0.8-0.rockspec
Cloning into 'lua-resty-etcd'...
warning: Could not find remote branch v0.8 to clone.
fatal: Remote branch v0.8 not found in upstream origin

Error: Failed cloning git repository.

It seems that rockspec refers to non existing tag v0.8:
https://github.com/iresty/lua-resty-etcd/blob/0.8/rockspec/lua-resty-etcd-0.8-0.rockspec#L5

why only json values

Hello everyone,

I was trying to replace Redis with etcd to keep my configurations between multiple regions but I checked api7 etcd library only supports values in json, why?

Doc: Running nginx tests failure. `unknown directive "lua_socket_log_errors"`

Hi.
I cloned the source code.
Installed some dependencies by the following instructions.
cpan Test::Nginx
brew install nginx version 1.19.5

I mkdir /Users/qinghao/Workspace/OpenSource/apisix/lua-resty-etcd/t/v2/t/servroot in my workdir.
And then I runned prove key.t.
After that I met some errors.

image

My lua version is 5.3.5

I searched it on Google. And it seems lua_socket_log_errors is an Nginx Module provided by openresty? But I'm not very familiar with that. Can anyone give me some clues.

Also, I think there should be some instruction guide for users to learn how to run the test... It takes me some time to figure out https://github.com/openresty/test-nginx has been used since I didn't know it at all before.
I can do that later.

@moonming

ngx.log(ngx.ERR, "failed to check value, got: ", data.body.kvs[1].value,

ngx.log(ngx.ERR, "failed to check value, got: ", data.body.kvs[1].value,

etcdctl can get the value:

image

local res, err = cli:get("/offline/999999999999999999999")
for k, v in pairs(res.body.kvs[1]) do
ngx.say(k , "=", v)
end

create_revision=372 mod_revision=372 key=/offline/999999999999999999999 version=1

raw serializer returns no value prop on keys created without quotation marks

etcdv3:get method table has no value prop. on keys created without double quotation marks:

> etcdctl put /foo/baz bar
OK
> etcdctl get /foo/baz    
/foo/baz
bar
content_by_lua_block {
    local etcd = require "resty.etcd"
    local cjson = require "cjson.safe"
    local json_encode = cjson.encode

    local conn, err = etcd.new({
        protocol = "v3",
        http_host = {
            "http://etcd1:2379",
            "http://etcd2:2379",
            "http://etcd3:2379",
        },
        serializer = "raw"
    })

    res, err = conn:get("/foo/baz")

    ngx.say(json_encode(res.body.kvs[1]))
}

{"version":"1","key":"\/foo\/baz","mod_revision":"19","create_revision":"19"}

But if you create key with double quotes:

> etcdctl put /foo/baz \"bar\"
OK
> etcdctl get /foo/baz
/foo/baz
"bar"

{"version":"3","key":"\/foo\/baz","create_revision":"19","mod_revision":"24","value":"bar"}

etcdv3:set method predictably puts values with quotation marks

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.