Giter Club home page Giter Club logo

redis2-nginx-module's Introduction

Name

ngx_redis2 - Nginx upstream module for the Redis 2.0 protocol

This module is not distributed with the Nginx source. See the installation instructions.

Table of Contents

Status

This module is already production ready.

Version

This document describes ngx_redis2 v0.15 released on 19 April 2018.

Synopsis

 location = /foo {
     set $value 'first';
     redis2_query set one $value;
     redis2_pass 127.0.0.1:6379;
 }

 # GET /get?key=some_key
 location = /get {
     set_unescape_uri $key $arg_key;  # this requires ngx_set_misc
     redis2_query get $key;
     redis2_pass foo.com:6379;
 }

 # GET /set?key=one&val=first%20value
 location = /set {
     set_unescape_uri $key $arg_key;  # this requires ngx_set_misc
     set_unescape_uri $val $arg_val;  # this requires ngx_set_misc
     redis2_query set $key $val;
     redis2_pass foo.com:6379;
 }

 # multiple pipelined queries
 location = /foo {
     set $value 'first';
     redis2_query set one $value;
     redis2_query get one;
     redis2_query set one two;
     redis2_query get one;
     redis2_pass 127.0.0.1:6379;
 }

 location = /bar {
     # $ is not special here...
     redis2_literal_raw_query '*1\r\n$4\r\nping\r\n';
     redis2_pass 127.0.0.1:6379;
 }

 location = /bar {
     # variables can be used below and $ is special
     redis2_raw_query 'get one\r\n';
     redis2_pass 127.0.0.1:6379;
 }

 # GET /baz?get%20foo%0d%0a
 location = /baz {
     set_unescape_uri $query $query_string; # this requires the ngx_set_misc module
     redis2_raw_query $query;
     redis2_pass 127.0.0.1:6379;
 }

 location = /init {
     redis2_query del key1;
     redis2_query lpush key1 C;
     redis2_query lpush key1 B;
     redis2_query lpush key1 A;
     redis2_pass 127.0.0.1:6379;
 }

 location = /get {
     redis2_query lrange key1 0 -1;
     redis2_pass 127.0.0.1:6379;
 }

Back to TOC

Description

This is an Nginx upstream module that makes nginx talk to a Redis 2.x server in a non-blocking way. The full Redis 2.0 unified protocol has been implemented including the Redis pipelining support.

This module returns the raw TCP response from the Redis server. It's recommended to use my lua-redis-parser (written in pure C) to parse these responses into lua data structure when combined with lua-nginx-module.

When used in conjunction with lua-nginx-module, it is recommended to use the lua-resty-redis library instead of this module though, because the former is much more flexible and memory-efficient.

If you only want to use the get redis command, you can try out the HttpRedisModule. It returns the parsed content part of the Redis response because only get is needed to implement.

Another option is to parse the redis responses on your client side yourself.

Back to TOC

Directives

Back to TOC

redis2_query

syntax: redis2_query cmd arg1 arg2 ...

default: no

context: location, location if

Specify a Redis command by specifying its individual arguments (including the Redis command name itself) in a similar way to the redis-cli utility.

Multiple instances of this directive are allowed in a single location and these queries will be pipelined. For example,

 location = /pipelined {
     redis2_query set hello world;
     redis2_query get hello;

     redis2_pass 127.0.0.1:$TEST_NGINX_REDIS_PORT;
 }

then GET /pipelined will yield two successive raw Redis responses

 +OK
 $5
 world

while newlines here are actually CR LF (\r\n).

Back to TOC

redis2_raw_query

syntax: redis2_raw_query QUERY

default: no

context: location, location if

Specify raw Redis queries and nginx variables are recognized in the QUERY argument.

Only one Redis command is allowed in the QUERY argument, or you'll receive an error. If you want to specify multiple pipelined commands in a single query, use the redis2_raw_queries directive instead.

Back to TOC

redis2_raw_queries

syntax: redis2_raw_queries N QUERIES

default: no

context: location, location if

Specify N commands in the QUERIES argument. Both the N and QUERIES arguments can take Nginx variables.

Here's some examples

 location = /pipelined {
     redis2_raw_queries 3 "flushall\r\nget key1\r\nget key2\r\n";
     redis2_pass 127.0.0.1:6379;
 }

 # GET /pipelined2?n=2&cmds=flushall%0D%0Aget%20key%0D%0A
 location = /pipelined2 {
     set_unescape_uri $n $arg_n;
     set_unescape_uri $cmds $arg_cmds;

     redis2_raw_queries $n $cmds;

     redis2_pass 127.0.0.1:6379;
 }

Note that in the second sample above, the set_unescape_uri directive is provided by the set-misc-nginx-module.

Back to TOC

redis2_literal_raw_query

syntax: redis2_literal_raw_query QUERY

default: no

context: location, location if

Specify a raw Redis query but Nginx variables in it will not be not recognized. In other words, you're free to use the dollar sign character ($) in your QUERY argument.

Only One redis command is allowed in the QUERY argument.

Back to TOC

redis2_pass

syntax: redis2_pass <upstream_name>

syntax: redis2_pass <host>:<port>

default: no

context: location, location if

phase: content

Specify the Redis server backend.

Back to TOC

redis2_connect_timeout

syntax: redis2_connect_timeout <time>

default: 60s

context: http, server, location

The timeout for connecting to the Redis server, in seconds by default.

It's wise to always explicitly specify the time unit to avoid confusion. Time units supported are s(seconds), ms(milliseconds), y(years), M(months), w(weeks), d(days), h(hours), and m(minutes).

This time must be less than 597 hours.

Back to TOC

redis2_send_timeout

syntax: redis2_send_timeout <time>

default: 60s

context: http, server, location

The timeout for sending TCP requests to the Redis server, in seconds by default.

It's wise to always explicitly specify the time unit to avoid confusion. Time units supported are s(seconds), ms(milliseconds), y(years), M(months), w(weeks), d(days), h(hours), and m(minutes).

Back to TOC

redis2_read_timeout

syntax: redis2_read_timeout <time>

default: 60s

context: http, server, location

The timeout for reading TCP responses from the redis server, in seconds by default.

It's wise to always explicitly specify the time unit to avoid confusion. Time units supported are s(seconds), ms(milliseconds), y(years), M(months), w(weeks), d(days), h(hours), and m(minutes).

Back to TOC

redis2_buffer_size

syntax: redis2_buffer_size <size>

default: 4k/8k

context: http, server, location

This buffer size is used for reading Redis replies, but it's not required to be as big as the largest possible Redis reply.

This default size is the page size, may be 4k or 8k.

Back to TOC

redis2_next_upstream

syntax: redis2_next_upstream [ error | timeout | invalid_response | off ]

default: error timeout

context: http, server, location

Specify which failure conditions should cause the request to be forwarded to another upstream server. Applies only when the value in redis2_pass is an upstream with two or more servers.

Here's an artificial example:

 upstream redis_cluster {
     server 127.0.0.1:6379;
     server 127.0.0.1:6380;
 }

 server {
     location = /redis {
         redis2_next_upstream error timeout invalid_response;
         redis2_query get foo;
         redis2_pass redis_cluster;
     }
 }

Back to TOC

Connection Pool

You can use the excellent HttpUpstreamKeepaliveModule with this module to provide TCP connection pool for Redis.

A sample config snippet looks like this

 http {
     upstream backend {
       server 127.0.0.1:6379;

       # a pool with at most 1024 connections
       # and do not distinguish the servers:
       keepalive 1024;
     }

     server {
         ...
         location = /redis {
             set_unescape_uri $query $arg_query;
             redis2_query $query;
             redis2_pass backend;
         }
     }
 }

Back to TOC

Selecting Redis Databases

Redis provides the select command to switch Redis databaess. This command is no different from other normal commands like get or set. So you can use them in redis2_query directives, for example,

redis2_query select 8;
redis2_query get foo;

Back to TOC

Lua Interoperability

This module can be served as a non-blocking redis2 client for lua-nginx-module (but nowadays it is recommended to use the lua-resty-redis library instead, which is much simpler to use and more efficient most of the time). Here's an example using a GET subrequest:

 location = /redis {
     internal;

     # set_unescape_uri is provided by ngx_set_misc
     set_unescape_uri $query $arg_query;

     redis2_raw_query $query;
     redis2_pass 127.0.0.1:6379;
 }

 location = /main {
     content_by_lua '
         local res = ngx.location.capture("/redis",
             { args = { query = "ping\\r\\n" } }
         )
         ngx.print("[" .. res.body .. "]")
     ';
 }

Then accessing /main yields

[+PONG\r\n]

where \r\n is CRLF. That is, this module returns the raw TCP responses from the remote redis server. For Lua-based application developers, they may want to utilize the lua-redis-parser library (written in pure C) to parse such raw responses into Lua data structures.

When moving the inlined Lua code into an external .lua file, it's important to use the escape sequence \r\n directly. We used \\r\\n above just because the Lua code itself needs quoting when being put into an Nginx string literal.

You can also use POST/PUT subrequests to transfer the raw Redis request via request body, which does not require URI escaping and unescaping, thus saving some CPU cycles. Here's such an example:

 location = /redis {
     internal;

     # $echo_request_body is provided by the ngx_echo module
     redis2_raw_query $echo_request_body;

     redis2_pass 127.0.0.1:6379;
 }

 location = /main {
     content_by_lua '
         local res = ngx.location.capture("/redis",
             { method = ngx.HTTP_PUT,
               body = "ping\\r\\n" }
         )
         ngx.print("[" .. res.body .. "]")
     ';
 }

Important The nginx variable $request_body only contains content buffered into memory. If nginx writes the request body to a temporary file (default behavior) the $request_body will not include the entire content or may be empty. It's recommended to use $echo_request_body which reads the full request body (regardless of being in buffer or temporary file).

This yeilds exactly the same output as the previous (GET) sample.

One can also use Lua to pick up a concrete Redis backend based on some complicated hashing rules. For instance,

 upstream redis-a {
     server foo.bar.com:6379;
 }

 upstream redis-b {
     server bar.baz.com:6379;
 }

 upstream redis-c {
     server blah.blah.org:6379;
 }

 server {
     ...

     location = /redis {
         set_unescape_uri $query $arg_query;
         redis2_query $query;
         redis2_pass $arg_backend;
     }

     location = /foo {
         content_by_lua "
             -- pick up a server randomly
             local servers = {'redis-a', 'redis-b', 'redis-c'}
             local i = ngx.time() % #servers + 1;
             local srv = servers[i]

             local res = ngx.location.capture('/redis',
                 { args = {
                     query = '...',
                     backend = srv
                   }
                 }
             )
             ngx.say(res.body)
         ";
     }
 }

Back to TOC

Pipelined Redis Requests by Lua

Here's a complete example demonstrating how to use Lua to issue multiple pipelined Redis requests via this Nginx module.

First of all, we include the following in our nginx.conf file:

 location = /redis2 {
     internal;

     redis2_raw_queries $args $echo_request_body;
     redis2_pass 127.0.0.1:6379;
 }

 location = /test {
     content_by_lua_file conf/test.lua;
 }

Basically we use URI query args to pass the number of Redis requests and request body to pass the pipelined Redis request string.

And then we create the conf/test.lua file (whose path is relative to the server root of Nginx) to include the following Lua code:

 -- conf/test.lua
 local parser = require "redis.parser"

 local reqs = {
     {"set", "foo", "hello world"},
     {"get", "foo"}
 }

 local raw_reqs = {}
 for i, req in ipairs(reqs) do
     table.insert(raw_reqs, parser.build_query(req))
 end

 local res = ngx.location.capture("/redis2?" .. #reqs,
     { body = table.concat(raw_reqs, "") })

 if res.status ~= 200 or not res.body then
     ngx.log(ngx.ERR, "failed to query redis")
     ngx.exit(500)
 end

 local replies = parser.parse_replies(res.body, #reqs)
 for i, reply in ipairs(replies) do
     ngx.say(reply[1])
 end

Here we assume that your Redis server is listening on the default port (6379) of the localhost. We also make use of the lua-redis-parser library to construct raw Redis queries for us and also use it to parse the replies.

Accessing the /test location via HTTP clients like curl yields the following output

OK
hello world

A more realistic setting is to use a proper upstream definition for our Redis backend and enable TCP connection pool via the keepalive directive in it.

Back to TOC

Redis Publish/Subscribe Support

This module has limited support for Redis publish/subscribe feature. It cannot be fully supported due to the stateless nature of REST and HTTP model.

Consider the following example:

 location = /redis {
     redis2_raw_queries 2 "subscribe /foo/bar\r\n";
     redis2_pass 127.0.0.1:6379;
 }

And then publish a message for the key /foo/bar in the redis-cli command line. And then you'll receive two multi-bulk replies from the /redis location.

You can surely parse the replies with the lua-redis-parser library if you're using Lua to access this module's location.

Back to TOC

Limitations For Redis Publish/Subscribe

If you want to use the Redis pub/sub feature with this module, then you must note the following limitations:

  • You cannot use HttpUpstreamKeepaliveModule with this Redis upstream. Only short Redis connections will work.
  • There may be some race conditions that produce the harmless Redis server returned extra bytes warnings in your nginx's error.log. Such warnings might be rare but just be prepared for it.
  • You should tune the various timeout settings provided by this module like redis2_connect_timeout and redis2_read_timeout.

If you cannot stand these limitations, then you are highly recommended to switch to the lua-resty-redis library for lua-nginx-module.

Back to TOC

Performance Tuning

  • When you're using this module, please ensure you're using a TCP connection pool (provided by HttpUpstreamKeepaliveModule) and Redis pipelining wherever possible. These features will significantly improve performance.
  • Using multiple instance of Redis servers on your multi-core machines also help a lot due to the sequential processing nature of a single Redis server instance.
  • When you're benchmarking performance using something like ab or http_load, please ensure that your error log level is high enough (like warn) to prevent Nginx workers spend too much cycles on flushing the error.log file, which is always non-buffered and blocking and thus very expensive.

Back to TOC

Installation

You are recommended to install this module (as well as the Nginx core and many many other goodies) via the ngx_openresty bundle. Check out the installation instructions for setting up ngx_openresty.

Alternatively, you can install this module manually by recompiling the standard Nginx core as follows:

  • Grab the nginx source code from nginx.org, for example, the version 1.11.2 (see nginx compatibility),
  • and then download the latest version of the release tarball of this module from ngx_redis2's file list.
  • and finally build the source with this module:
 wget 'http://nginx.org/download/nginx-1.11.2.tar.gz'
 tar -xzvf nginx-1.11.2.tar.gz
 cd nginx-1.11.2/

 # Here we assume you would install you nginx under /opt/nginx/.
 ./configure --prefix=/opt/nginx \
             --add-module=/path/to/redis2-nginx-module

 make -j2
 make install

Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the --add-dynamic-module=PATH option instead of --add-module=PATH on the ./configure command line above. And then you can explicitly load the module in your nginx.conf via the load_module directive, for example,

load_module /path/to/modules/ngx_http_redis2_module.so;

Back to TOC

Compatibility

Redis 2.0, 2.2, 2.4, and above should work with this module without any issues. So is the Alchemy Database (aka redisql in its early days).

The following versions of Nginx should work with this module:

  • 1.17.x (last tested: 1.17.4)
  • 1.16.x
  • 1.15.x (last tested: 1.15.8)
  • 1.14.x
  • 1.13.x (last tested: 1.13.6)
  • 1.12.x
  • 1.11.x (last tested: 1.11.2)
  • 1.10.x
  • 1.9.x (last tested: 1.9.15)
  • 1.8.x
  • 1.7.x (last tested: 1.7.10)
  • 1.6.x
  • 1.5.x (last tested: 1.5.12)
  • 1.4.x (last tested: 1.4.3)
  • 1.3.x (last tested: 1.3.7)
  • 1.2.x (last tested: 1.2.7)
  • 1.1.x (last tested: 1.1.5)
  • 1.0.x (last tested: 1.0.10)
  • 0.9.x (last tested: 0.9.4)
  • 0.8.x >= 0.8.31 (last tested: 0.8.54)

Earlier versions of Nginx will not work.

If you find that any particular version of Nginx above 0.8.31 does not work with this module, please consider reporting a bug.

Back to TOC

Community

Back to TOC

English Mailing List

The openresty-en mailing list is for English speakers.

Back to TOC

Chinese Mailing List

The openresty mailing list is for Chinese speakers.

Back to TOC

Bugs and Patches

Please submit bug reports, wishlists, or patches by

  1. creating a ticket on the GitHub Issue Tracker,
  2. or posting to the OpenResty community.

Back to TOC

Source Repository

Available on github at openresty/redis2-nginx-module.

Back to TOC

TODO

  • Add the redis2_as_json directive to allow emitting JSON directly.

Back to TOC

Author

Yichun "agentzh" Zhang (章亦春) [email protected], OpenResty Inc.

Back to TOC

Getting involved

You'll be very welcomed to submit patches to the author or just ask for a commit bit to the source repository on GitHub.

Back to TOC

Copyright & License

This module is licenced under the BSD license.

Copyright (C) 2010-2018, by Yichun "agentzh" Zhang (章亦春) [email protected], OpenResty Inc.

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Back to TOC

SEE ALSO

Back to TOC

redis2-nginx-module's People

Contributors

agentzh avatar calio avatar charlesportwoodii avatar chipitsine avatar hnakamur avatar stevepeak avatar thibaultcha avatar xiaocang avatar zhuizhuhaomeng 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  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

redis2-nginx-module's Issues

no redis2 query specified or the query is empty

## Get Below Error with nginx so please help to fix that

2016/11/27 03:50:30 [error] 7294#0: *66 no redis2 query specified or the query is empty, client: 150.107.101.46, server: localhost, request: "GET / HTTP/1.1", subrequest: "/redis_get", host: "localhost", referrer: "https://localhost/admin"
2016/11/27 03:50:30 [error] 7294#0: *66 no redis2 query specified or the query is empty, client: 150.107.101.46, server: localhost, request: "GET /activity HTTP/1.1", subrequest: "/redis_get", host: "localhost", referrer: "https://localhost/admin"
2016/11/27 03:50:36 [error] 7294#0: *75 no redis2 query specified or the query is empty, client: 150.107.101.46, server: localhost, request: "GET /blog/all HTTP/1.1", subrequest: "/redis_get", host: "localhost", referrer: "https://localhost/activity"
2016/11/27 03:50:36 [error] 7294#0: *75 no redis2 query specified or the query is empty, client: 150.107.101.46, server: localhost, request: "GET /bookmarks/all HTTP/1.1", subrequest: "/redis_get", host: "localhost", referrer: "https://localhost/activity"
2016/11/27 03:50:37 [error] 7294#0: *72 no redis2 query specified or the query is empty, client: 150.107.101.46, server: localhost, request: "GET /file/all HTTP/1.1", subrequest: "/redis_get", host: "localhost", referrer: "https://localhost/activity"
2016/11/27 03:50:42 [error] 7294#0: *82 no redis2 query specified or the query is empty, client: 150.107.101.46, server: localhost, request: "GET /groups/all HTTP/1.1", subrequest: "/redis_get", host: "localhost", referrer: "https://localhost/activity"

Nginx version and conf file info:

./nginx -V
nginx version: openresty/1.11.2.2
built by gcc 4.8.2 20131212 (Red Hat 4.8.2-8) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/local/openresty/nginx --with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.3.0 --add-module=../echo-nginx-module-0.60 --add-module=../xss-nginx-module-0.05 --add-module=../ngx_coolkit-0.2rc3 --add-module=../set-misc-nginx-module-0.31 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.06 --add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10.7 --add-module=../ngx_lua_upstream-0.06 --add-module=../headers-more-nginx-module-0.32 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.17 --add-module=../redis2-nginx-module-0.13 --add-module=../redis-nginx-module-0.3.7 --add-module=../rds-json-nginx-module-0.14 --add-module=../rds-csv-nginx-module-0.07 --with-ld-opt=-Wl,-rpath,/usr/local/openresty/luajit/lib --with-http_ssl_module

**see mine attached nginc.conf file **

nginx_redis_cache.txt

Getting rid of the $number response without lua

Hello there.
I'm willing to use the redis2 module to retrieve static files from my redis DB and to return them as is.
For some reason, although according to documentation I get a $number as the first line of the response. The way it's described in the README:
... then GET /pipelined will yield two successive raw Redis responses
+OK
$5
world

It's not really clear why is the $5 ever needed.
I understand I can use LUA to get rid of it, but that seems like an unnecessary overhead.

Thanks.

Redis2_pass with <host>:<port> from $args fail

I'm trying to address several redis instances, dispatching it on a host:port basis (one single backend location)

here my nginx.conf location
...
location /redis_backend {
internal;
set_unescape_uri $verb $arg_verb;
set_unescape_uri $key $arg_key;
set_unescape_uri $r_host $arg_host;
set_unescape_uri $r_port $arg_port;
redis2_query $verb $key;
redis2_pass $r_host:$r_port;
}
...

I call /redis_backend location from a lua like this:

....
r_instance["redis_host"] = '127.0.0.1'
r_instance["redis_port"] = '33001'
....
local res = ngx.location.capture (
"/redis_backend",
{ args =
{ verb = r_verb,
key = redis_key,
host = r_instance["redis_host"],
port = r_instance["redis_port"],
}
}
)
...

in nginx error log (i use the openresty suite ngx_openresty/1.0.10.44), I got this error
2012/04/07 19:25:03 [error] 11715#0: *1 redis2: upstream "127.0.0.1:33001" not found, client: 127.0.0.1, server: ....

I'm sure redis instance is up&running. I'm able to connect to her via redis-cli or, simply setting redis2_pass 127.0.0.1:33001;

ciao
massimo

QUESTION: Can I use redis return to identify my upstream?

So, I want use this module to consult in redis which server I will redirect for specific KEY, like this

My servers list in redis (this will be dynamic list):
(key -> value)

key1 -> 127.0.0.1
key2 -> 127.0.0.2

Request received in NGINX:

/get?key=key1

Nginx redirect my request to 127.0.0.1

with this module I can do it?

Very simple scripting without Lua?

I would like to do a SETNX and if that succeeded do an INCR. I hoped I could do this without Lua. By my (admittedly limited) understanding I would need a variable which contains the redis reply so i can an nginx if() on it?

Authentication Support

Hello,

Is password authentication supported by this module? I could not find anything in the docs for this. I am trying to connect to a rediscloud endpoint:

redis://redistogo:[email protected]:9797

Thanks.

nginx proxy_cache with redis_pass

Hi agentzh,

I am using redis2 module for connecting openresty with redis. I want to avoid roundtrip time b/w servers and redis by caching the redis response on the local disk for a very small amount of time.

Here is my standalone example:

#Proxy cache
proxy_cache_path cache keys_zone=rediscache:5m max_size=20m;

location /redis_get {
internal;
proxy_pass_request_headers off;
set_unescape_uri $key $arg_key; # this requires ngx_set_misc
redis2_query get $key;
redis2_pass $redis_slave;
proxy_ignore_headers Cache-Control;
proxy_temp_path cache/tmp;
proxy_cache_use_stale updating;
proxy_cache_lock on;
proxy_cache_valid any 30m;
proxy_cache rediscache;
}

But this is not caching the response on the disk. The local disk does not contain any files. Also, when I run MONITOR on redis, I can see the commands getting sent on the redis.

Any help would be appreciated.

Using redis2_query in combination with try_files

I would like to be able to save request data in Redis and utilize a callback to show the user a page once the Redis query finished running.

Example:

location = / {
  # Store something in Redis:
  redis2_query set "somekey" $some_variable;
  redis2_pass redis;
  # Serve content to the user:
  post_action /showpage;
}

location /showpage {
  # Serve file:
  try_files $uri /somefile.html;
}

Is there any way to implement this or can this be added in a future release?

nginx不返回数据,而是下载

image
我实在找不到原因,希望能帮助我

一直用的redis2-nginx-module,这次新配置的和之前的一样的。但是出现了这个问题:

我访问这个链接的时候nginx返回的是让下载文件,文件的内容是本应该放回的数据。我用的php那些请求是没有问题的

redis_pass报500错误

location = /tt {
default_type 'text/html';
expires -1;
set $ud "aaaaaaaa";
if ($http_user_agent ~ MSIE) {
set $ud "bbbbbbbbb";
}
redis2_query incr "a1";
redis2_query sadd "ud" $ud;
redis2_pass redis_server;
}
这个配置会出现500错误,如果去掉
if ($http_user_agent ~ MSIE) {
set $ud "bbbbbbbbb";
}
就OK。我的版本是1.0.12,请大神分析下啊

How to know if the redis connected ?

Hi,

Now I want to implement the following function, I want to tell our clients if the data pushed to the redis so that clients can delete local cache. So I want to know if the redis server is ready to accepts requests.

And how to implement this?

Thanks

specify timeout directives use seconds

some nginx proxy_pass style modules use milliseconds for timeout values (HttpMemcached) while some use seconds (HttpProxyModule). redis2-nginx-module uses seconds, it'd be nice if someone could add this to the README for new users.

thanks, love the module!

does `redis2_raw_queries` support transaction or has bug ?

my nginx version is 1.8.1 and redis version is 2.8.1, when I used command redis2_raw_queries, like this:

redis2_raw_queries 4 "multi\r\nhmset $msec:header host $host remote_addr $remote_addr remote_port $remote_port request_uri $request_uri status $status\r\nsadd member:header $msec:$request_uri\r\nexec\r\n";

Finally, I got different numbers of hash key and set collection members , but there is no errors in error.log . Always, set collection has more members than has keys in redis .
however, when I use double redis2_query command to execute hmset and sadd, the result is OK .

Can't get back multi-bulk reply from lua

...or what I assume is a multi-bulk reply

Request command is EVAL, put together with redis.parser.build_query
res = ngx.location.capture tells redis2 location that it's 1 query (also tried 2)

redis-lua returns following (tcpdump):

*2
*0
:1

First result is an empty zset result, 2nd is an integer...
When I print out res, it's

unnamed = {
["status"] = 200;
["body"] = "";
["header"] = {
["Content-Type"] = "application/octet-stream";
};
["truncated"] = "false";
};

Redis commandline client says

  1. (empty list or set)
  2. (integer) 1

I'd try resty-redis, but I need nginx to shard the queries across multiple redis servers

typo

redis2-nginx-module / src / ngx_http_redis2_handler.c
line 215

Did you mean headers?

请教

first conf:
location /news {
# content_by_lua_file conf/news.lua;
# echo $res;

     content_by_lua '
           local res = ngx.location.capture("/redis",
                { args = { query = "ping\\r\\n" } }
            )
            ngx.print("[" .. res.body .. "]")
        ';
    }

return result:[+PONG
]

second conf:
location /news {
content_by_lua_file conf/news.lua;
# echo $res;

     #content_by_lua '
     #      local res = ngx.location.capture("/redis",
     #           { args = { query = "ping\\r\\n" } }
     #       )
     #       ngx.print("[" .. res.body .. "]")
     #   ';
    }

news.lua:
local res = ngx.location.capture("/redis",
{ args = { query = "ping\r\n" } }
)
ngx.print("[" .. res.body .. "]")

return result: []

can you tell me the errors?

suggestion how to handle redis errors

I would like to know your opinion how to handle a redis error, in my case a Redis Evalsha issue due to malformed parameter

-ERR Error running script (call to f_ea25fc9ab8e5cb16221ba7d56aabcd764e112abb): @user_script:7: user_script:7: attempt to compare number with string

is the only way the Redis response parser? is it not overkill?
maybe a flag in redis_pass to handle an error?

Thanks!

in redis not store Keys of all URL

Please help me to fix store redis key in redis
X-Cached-From: MISS for all after hit url many times

because it is trying to get that key but that key is not seen in redis db

[root@dipen conf]# redis-cli monitor
1480268347.871964 "select" "0"
1480268347.871980 "get" "c40932017eaa71e8eb07236f7a351d49"
1480268351.175680 "ttl" "c40932017eaa71e8eb07236f7a351d49"
1480268352.208962 "select" "0"
1480268352.208978 "get" "316e2b0423dd1b6fbce5051b43b36a94"
1480268352.947172 "ttl" "316e2b0423dd1b6fbce5051b43b36a94"

[root@dipen conf]# redis-cli
redis 127.0.0.1:6379> KEYS *
(empty list or set)
redis 127.0.0.1:6379>

## Nginx.conf File
nginx_redis_cache.txt

high cpu usage when using lua-resty-redis

 2

 1
user dweihang;
worker_processes 2 ;
worker_cpu_affinity 0001 0010;
worker_rlimit_nofile 100000;

error_log logs/error.log;

events {
worker_connections 100000;
}

http {
lua_package_path "/usr/local/lua-resty-redis/lib/?.lua;;";

geoip_country /data/geoip/GeoIP.dat;
geoip_city    /data/geoip/GeoLiteCity.dat;

keepalive_timeout 5;

map $uri $lua_uritmp{
default "";
~^(?P<key>.+)$ $key;
}
 server {
   listen 80;
   location /test1 {
    set $lua_country    us;
    set $remoteip       "";
        rewrite_by_lua '
    redis  = require "resty.redis"

    function get_testdemo_server()  
    local testdemo   = redis:new()
    testdemo:set_timeout(1000) 
    local  ok,err = testdemo:connect("127.0.0.1",6379)
        if not ok then
        ngx.say("faild to connect",err)
        return nil,err
        end
    return testdemo
    end 

    local  luacountry = ngx.var.lua_country
        local  luauri     = ngx.var.lua_uritmp
    local  testdemo = get_testdemo_server()
    local exist = testdemo:exists(luauri)    --query the luauri whether exists in redis
    if exist==0 or testdemo:sismember(luauri,luacountry)==0 then 
            ngx.say("request not found")
        elseif  luacountry=="us" then
            ngx.var.remoteip = testdemo:rpoplpush("US","US")
            ngx.say(ngx.var.remoteip)
        elseif luacountry=="eu" then
            ngx.var.remoteip = testdemo:rpoplpush("EU","EU")
    elseif luacountry=="eu" then
                            ngx.var.remoteip = testdemo:rpoplpush("ASIA","ASIA")
    else 
            ngx.say("fuck that")
    end
    local ok, err = testdemo:set_keepalive(0, 10000)
        if not ok then
            ngx.say("failed to set keepalive: ", err)
            return
        end
    ';
#proxy_pass http://$remoteip$request_uri;
echo "helllo";
}

}
}

The cpu usage become very high when I run Apache ab test.
I run apache ab commands as follows:
ab -k -c 100 -n 100000 http://192.168.162.129/test1
I also ulimit -n 100000
The purpose of the configuration aboved is to query the country's server corresponding IP from redis database and proxy requests to the corresponding server. And I used redis command "rpoplpush" to implement a simple round-robin load-balancer. (e.g. assuming that there more than one server in US) The reason why I used "rpoplpush" command is that I could easily remove or add server by redis-cli. But when I used the aboved configuration,the cpu usage became very high.
Any ideas or solutions to enhance the performance, I used my laptop to do the test...and my laptop is a little bit out of date.

redis2-nginx-module Module installation problem

My system is ubuntu14.04
apt-get install libreadline-dev libpcre3-dev libssl-dev perl build-essential
I installed these options
./configure --prefix=/opt/openresty
--without-http_redis2_module
--without-http_redis_module
--without-lua_resty_redis
--without-lua_cjson
--with-http_iconv_module
--without-http_set_misc_module
The installation process without any problems,Nginx is running normally,Can parse lua
But can't identify redis2
unknown directive "redis2_query"
On the Internet looking for a long time didn't find the solution,Redis can run normally
I install ngx_openresty-1.7.4.1

Add directive/option for parsed response

Right now I get my data prefixed with $99\r\n\r\n for a simple get, and there does not seem to be an easy way with nginx (without Lua) to remove this before using it further or returning it. The lua-redis-parser module does not seem to be usable without Lua for instance..

So perhaps we can add a redis2_query_parsed directive, or adding a flag to redis2_query?

Alternative is using nginx-redis-module, but that seems to be pretty unmaintained..

Getting value from redis

Hi,

when I try to get a value from redis, I'm getting a weird value along with the result that I want:

$17
74.125.225.136:80

Any idea what $17 is?

thanks

Further plans for redis2-nginx-module

Hello,

What are your plans for this module? Are any new releases expected?

We are creating a service that should be able to return JSON representing contents of Redis HMAP for a given identifier (Redis key). This service is expected to be loaded with approx 10..20k queries per second. We performed some JMeter tests and saw that with redis2-nginx-module and load balancing we can achieve what we need using a small number of nginx servers.

The things that we would like to get are:

  1. redis2_as_json -- are you really going to implement this? For us, this might be more convenient than to prepare JSON in advance, though throughput might be lower -- we should measure it.

  2. The module always returns raw response from Redis, i. e. $&lt;Length&gt;&lt;Content&gt; format. We don't need '$&lt;Length>' part, can we get rid of it? Can Unicode characters such as \u0442 be encoded in UTF-8?

  3. Any Redis 3.0 Cluster support?

If there is something that can be done on a fee basis, we are ready to discuss.

Looking forward for your answer,

Regards,

Ivan

Redis to JSON

Not really an issue but more so a question. Is it possible to convert redis output to JSON similar to the RDS to JSON with the postgres module?

Thanks,
Carl

您好

您好,章老师,ngx_http_redis_process_header
upstream 读后端redis的数据,怎么才知道读完了没? 以前http 是一个hander的长度,根据这个长度,来对比知道读了多少~ 但是redis协议里面没有这样的~
如果遇到大value, 我怎么判断才能把value读完,然后解析解析处理包装~

how to connect the redis that requires a password?

redis2_pass :
how to enter the password?
I can connect the redis with the command:
redis-cli -h 192.168.55.33 -p 6379 -a mypassword
but how to use redis2 to connect the redis that requires a password

"Redis server returned invalid response"

The response seems to be valid; but I get an error:

[error] 23868#0: *148 Redis server returned invalid response near pos 18 in "+OK
+QUEUED
*1
*85
$1
1
$1
2
$1
3
$1
4
$1
5
$1
6
$1
7
$1
8
$1
9
$2
10
$2
11
$2
12
$2
13
$2
14
$2
15
$2
16
$2
17
$2
18
$2
19
$2
20
$2
21
$2
22
$2
23
$2
24
$2
25
$2
26
$2
27
$2
28
$2
29
$2
30
$2
31
$2
32
$2
33
$2
34
$2
35
$2
36
$2
37
$2
38
$2
39
$2
40
$2
41
$2
42
$2
43
$2
44
$2
45
$2
46
$2
47
$2
48
$2
49
$2
50
$2
51
$2
52
$2
53
$2
54
$2
55
$2
56
$2
57
$2
58
$2
59
$2
60
$2
61
$2
62
$2
63
$2
64
$2
65
$2
66
$2
67
$2
68
$2
69
$2
70
$2
71
$2
72
$2
73
$2
74
$2
75
$2
76
$2
77
$2
78
$2
79
$2
80
$2
81
$2
82
$2
83
$2
84
$2
85
" while reading response header from upstream, client: XXXXXXXXX, server: , request: "GET XXXXXXXXXXXXX", subrequest: "/redis", upstream: "redis2://127.0.0.1:6379", host: "XXXXXXXXXXXXX"

[emerg] 14574#0: unknown directive "redis2_query" in /usr/local/openresty/nginx/conf/nginx.conf

When i try to use HttpRedis2Module in Openresty and try to reload my nginx server in Openresty, it occurred an error : "unknown directive "redis2_query" in /usr/local/openresty/nginx/conf/nginx.conf".

Why the directive of "redis2_query" is unknown in Openresty ? My Openresty's Version is 1.13.6.2 .

I sure that my compile configuration doesn't have --without-http_redis2_module.

Here is my nginx.conf partial Configuration :

location /http2redisget {
set $key hello;
redis2_query get $key;
redis2_pass 127.0.0.1:6379;
}

how to use with nginx rewrite?

Hi, Agentzh
I added redis2 module in nginx to collect some data, then nginx does rewrite url work. Unfortunately, redis2 module does not work as expected. The conf slice like:
server {
location /adc {
redis2_query incr test;
redis2_pass 127.0.0.1:6379;
}
rewrite ^/adc/(.*)$ /adagent/clk.php last;
}
Can you give some suggestions?
Thanks.

QUESTION: store POST message body to redis

How can I write the nginx config to store the image to redis

curl -X POST localhost:80/upload/123 --data-binary "@lena.png"

I am trying to use $request_body but it doesn't work as I guess this variable value isn't available in this location.

location ~ /upload/(.*) { redis2_query set $1 $request_body; redis2_pass 172.17.0.4:6379; }
The expected result is to store the image binary data under the 123 key passed as query param.
Is there any way to do that?

UPDATE:
I used the https://github.com/klestoff/read-request-body-nginx-module read_request_body; directive. In this case, I am not able to send image bigger than client_body_buffer_size (default value is 16k) which is bad in if the image is bigger.

variable is null when included in access log path

Hi, agentzh
I was troubled by this issue these days. I wanna seperated logs according to location rules, so I used a variable to do this. But some error messages occur in error.log like that :
open() "/data/nginx/logs/.log" failed (13: Permission denied) while logging request

And the nginx.conf slice is :
server {
set $logname access;

    location /adt {
        set $logname imp;
    }

   log_format main "........";
   access_log  logs/$logname.log  main;
   open_log_file_cache max=1000 inactive=20s min_uses=2 valid=1m;

}
and Nginx Version is 1.0.11

Can you give me some points? Thanks.

“OOM command not allowed” response on redis2_pass should alert to nginx error.log

While using redis2_pass and redis2_query in openresty location config, I can't get an error message in nginx logs in the situation, when redis.conf has those lines:

maxmemory 1073741824
maxmemory-policy noeviction

If the limit of used RAM by the redis instance was reached, redis start to reply with "OOM command not allowed" error to the push command.

Why didn't nginx print error message while it can't push data to redis cause of OOM on it?

No route to host

2015/06/17 10:29:32 [error] 18475#0: *3 connect() failed (113: No route to host) while connecting to upstream

Installation problem

This module has really undescribed installation!
where is:
/opt/nginx?
where is:
/path/to/redis2-nginx-module
where is:
load_module /path/to/modules/ngx_http_redis2_module.so;

Please help me and give me working installation command lines.

nginx make error

system info

  • ubuntu 14.0.1 server

openresty version

  • openresty-1.11.2.3

make

  • sudo make -j2

error code

objs/addon/src/ngx_http_redis2_module.o:(.data+0x0): multiple definition of `ngx_http_redis2_module'
objs/addon/src/ngx_http_redis2_module.o:(.data+0x0): first defined here
objs/addon/src/ngx_http_redis2_handler.o: In function `ngx_http_redis2_handler':
/home/www/openresty-1.11.2.3/../redis2-nginx-module-0.14/src/ngx_http_redis2_handler.c:23: multiple definition of `ngx_http_redis2_handler'
objs/addon/src/ngx_http_redis2_handler.o:/home/www/openresty-1.11.2.3/../redis2-nginx-module-0.14/src/ngx_http_redis2_handler.c:23: first defined here
objs/addon/src/ngx_http_redis2_reply.o: In function `ngx_http_redis2_process_reply':
/home/www/openresty-1.11.2.3/build/nginx-1.11.2/src/ngx_http_redis2_reply.rl:26: multiple definition of `ngx_http_redis2_process_reply'
objs/addon/src/ngx_http_redis2_reply.o:/home/www/openresty-1.11.2.3/build/nginx-1.11.2/src/ngx_http_redis2_reply.rl:26: first defined here
objs/addon/src/ngx_http_redis2_util.o: In function `ngx_http_redis2_set_complex_value_slot':
/home/www/openresty-1.11.2.3/../redis2-nginx-module-0.14/src/ngx_http_redis2_util.c:21: multiple definition of `ngx_http_redis2_set_complex_value_slot'
objs/addon/src/ngx_http_redis2_util.o:/home/www/openresty-1.11.2.3/../redis2-nginx-module-0.14/src/ngx_http_redis2_util.c:21: first defined here
objs/addon/src/ngx_http_redis2_util.o: In function `ngx_http_redis2_upstream_add':
/home/www/openresty-1.11.2.3/../redis2-nginx-module-0.14/src/ngx_http_redis2_util.c:55: multiple definition of `ngx_http_redis2_upstream_add'
objs/addon/src/ngx_http_redis2_util.o:/home/www/openresty-1.11.2.3/../redis2-nginx-module-0.14/src/ngx_http_redis2_util.c:55: first defined here
objs/addon/src/ngx_http_redis2_util.o: In function `ngx_http_redis2_build_query':
/home/www/openresty-1.11.2.3/../redis2-nginx-module-0.14/src/ngx_http_redis2_util.c:116: multiple definition of `ngx_http_redis2_build_query'
objs/addon/src/ngx_http_redis2_util.o:/home/www/openresty-1.11.2.3/../redis2-nginx-module-0.14/src/ngx_http_redis2_util.c:116: first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [objs/nginx] Error 1
make[2]: Leaving directory `/home/www/openresty-1.11.2.3/build/nginx-1.11.2'
make[1]: *** [build] Error 2
make[1]: Leaving directory `/home/www/openresty-1.11.2.3/build/nginx-1.11.2'
make: *** [all] Error 2

Get content from Redis with "\r\n" in text fails with "Redis server returned extra bytes"

I'm trying to fetch some content from redis using Redis2 module, that has line break "\r\n" inside of content. However this fails with: "Redis server returned extra bytes".

Full example:
First set some values in redis, to use later (we set a simple text, and than with \r\n inside):

redis> hset "/step2redisallhget?auctionid=1l" "content" "a 1line"
(integer) 1
redis> hset "/step2redisallhget?auctionid=2l" "content" "a 1line \r\n and 2nd"
(integer) 1

Now test some values in redis-cli
redis> hget "/step2redisallhget?auctionid=1l" "content"
"a 1line"
redis> hget "/step2redisallhget?auctionid=2l" "content"
"a 1line \r\n and 2nd"

Now test in nginx redis2 module with a 1line content:
http://adserver.local/getredisresponse3?hash_key=/step2redisallhget?auctionid=1l
Result:
*1
$7
a 1line

And now with 2line content that fails.
http://adserver.local/getredisresponse3?hash_key=/step2redisallhget?auctionid=2l
Result:
(in browser returns 200=OK, however content is empty)

And then verification of nginx error log:
2011/06/08 10:10:31 [error] 18559#0: *11 Redis server returned extra bytes: " and 2nd
" (len 10) while reading response header from upstream, client: 192.168.1.1, server: adserver.local, request: "GET /getredisresponse3?hash_key=/step2redisallhget?auctionid=2l HTTP/1.1", host: "adserver.local"

My nginx.conf (part of)
location /getredisresponse3
{
set_unescape_uri $key $arg_hash_key;
redis2_query hmget $key "content";
redis2_pass redisbackend;
}

And configuration:
nginx: nginx version: nginx/1.0.2
nginx: built by gcc 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
nginx: TLS SNI support enabled
nginx: configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --user=www-data --group=www-data --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --with-cc-opt=-O2 --with-http_gzip_static_module --with-http_ssl_module --with-http_geoip_module --with-http_realip_module --with-http_stub_status_module --sbin-path=/usr/sbin/nginx --with-ld-opt=-lossp-uuid --with-cc-opt=-I/usr/include/ossp --add-module=/home/uporabnik/simpl-ngx_devel_kit-bc97eea --add-module=/home/uporabnik/chaoslawful-lua-nginx-module-48063d3 --add-module=/home/uporabnik/agentzh-headers-more-nginx-module-28c62d1 --add-module=/home/uporabnik/ngx_http_redis-0.3.2 --add-module=/home/uporabnik/agentzh-redis2-nginx-module-275233d --add-module=/home/uporabnik/catap-ngx_http_upstream_keepalive-a0073ac --add-module=/home/uporabnik/agentzh-echo-nginx-module-1c4e116 --add-module=/home/uporabnik/newobj-nginx-x-rid-header-92f9a11 --add-module=/home/uporabnik/agentzh-set-misc-nginx-module-13faacd --add-module=/home/uporabnik/substitutions4nginx-read-only

Mix redis2_query with empty_gif module

Hi,

I wanna implement simple counter bassed on redis

location = /counter.gif {
redis2_pass redis_backend;
redis2_query incr counter;
access_log off;
empty_gif;
add_header Cache-Control "max-age=0, no-cache, no-store";
}

The main problem is that redis2_query return the value into nginx buffer and broke the output. Is there any posibility to mix this together? Maybe redis_silent_query would be good if you wanna implement?

Unable to select a database while connecting.

All though the usage of databases in Redis seems some what useless. its a really handy feature when hosting multiple websites on the same server to avoid key collision.

Could we add this feature or put it into the documentation if it already exists?

"MULTI & LRANG" BUG

When using MULTI AND LRANG together will cause error "Redis server returned invalid response near pos 18 in "

conf like this:
"
redis2_query MULTI;
redis2_query LRANGE "dict" 0 0;
redis2_query EXEC;
"

redis 127.0.0.1:6379> EXEC

    1. "2"
    2. "1"
      MAY BE" 1) 1)" tigger the error info.

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.