Nginx_lua Case Study: Dynamic routing implementation

Source: Internet
Author: User
The route here refers to the mapping of the access path and the specific implementation content in Web development. For example,/a maps to a specific page, which is called a route. Dynamic routing, as the name implies, dynamically adds this route-mapping relationship.

In Nginx, route mappings or reverse proxies are implemented through rewrite and Proxy_pass, but this relationship must be written to die in the configuration file according to the traditional configuration, and then the Nginx can be restarted quickly and "seamlessly". Although seamless, its cumbersome configuration and tedious restart operations are still unavoidable.

Recently, on GitHub to see a project Ceryx, is nginx combined with LUA Dynamic route mapping, that is, the above-mentioned mapping relationship, using LUA to manage, although it is relatively simple implementation, but can be analyzed under the study. The project preserves this mapping by using the structure of Redis, so that the relationship can be quickly obtained in nginx so as to handle it, and exposes an interface that manages the routing relationship with Redis in the form of HTTP.

From ceryx.db Import redisrouterresource_fields = {' Source ': Fields. String, ' target ': fields. String,}parser = Reqparse. Requestparser () parser.add_argument (' source ', Type=str, required=true, help= ' source is required ') parser.add_argument (' Target ', Type=str, required=true, help= ' target is required ') router = redisrouter.from_config () def lookup_or_abort (so Urce): "" Returns the target for the given source, or aborts raising a 404 "" "Try:return {' source ': Source, ' Target ': router.lookup (source)} except RedisRouter.LookupNotFound:abort (404, message= ' Rout E with source {} doesn\ ' t exist '. Format (source)) class Route (Resource): "" "Resource describing a single Rout E. Supports GET, DELETE and PUT.    The format is the following: "' {" source ":" [Source] "," target ":" [Target] "}" "" @marshal_with (Resource_fields) def get (self, source): ' "" fetches the route with the given SOURce "" "route = Lookup_or_abort (source) return Route @marshal_with (resource_fields) def delete (         Self, source): "" "Deletes the route with the given source" "" route = lookup_or_abort (source)        Router.delete (source) return route, 204 @marshal_with (Resource_fields) def put (self, source): "" "creates or updates the route with the given source, pointing to the given target" "" Args = Parser.parse_args () router.insert (args[' source '), args[' target ') return args, 201

The above code, is the HTTP API for routing management, of course, this is not the focus of our analysis. Let's take a look at the configuration of Nginx in this project.

Upstream fallback {    server www.something.com;} server {    listen;    Default_type text/html;    Location/{        set $container _url "fallback";        Resolver 8.8.8.8;        # Lua Files        access_by_lua_file lualib/router.lua;//pointcut        # Proxy configuration        proxy_set_header Host $http _ Host;        Proxy_set_header x-forwarded-for $proxy _add_x_forwarded_for;        Proxy_set_header  x-real-ip  $remote _addr;        Proxy_set_header X-forwarded-proto $scheme;        Proxy_redirect ~^ (http://[^:]+): \d+ (/.+) $ $;        Proxy_redirect//;        # Upgrade Headers        proxy_http_version 1.1;        Proxy_set_header Upgrade $http _upgrade;        Proxy_set_header Connection "Upgrade";        Proxy_pass http://$container _url$request_uri;    }    ...}
Can simply see, this configuration is quite common, and the normal reverse proxy is no different, the real point of entry is access_by_lua_file inside the Router.lua code.

Local Container_url = ngx.var.container_url//get the container_urllocal host in the config file = ngx.var.host//host when the request is received, e.g. we request HTTP ://www.xxx.com/a.html The host here is www.xxx.com--Check if key exists in local cachelocal cache = Ngx.shared.ceryxlocal res, f lags = Cache:get (host)//directly in the Nginx cache with the corresponding route map, if there is a direct return to the result if res then Ngx.var.container_url = Res Returnendl Ocal Redis = require "Resty.redis"//Redis connection code is connected every time redis,local red = redis:new ()//This operation is relatively time-consuming, so the next operation will be in the local cache to save the corresponding relationshipRed:set_timeout--Mslocal redis_host = os.getenv ("Ceryx_redis_host") if not redis_host then Redis_host = "127.0.0 .1 "Endlocal redis_port = os.getenv (" Ceryx_redis_port ") if not redis_port then Redis_port = 6379 endlocal res, err = Red:co Nnect (Redis_host, Redis_port)--Return if could not connect to Redisif not res then returnend--Construct Redis Keyloca L prefix = os.getenv ("Ceryx_redis_prefix") if not prefix then prefix = "Ceryx" endlocal key = prefix. ": Routes:". host--Try to get the target for hostres, err = red:get (key) if not res or res = = Ngx.null then--Construct Redis key for $ Wildcard key = prefix. ": Routes: $wildcard" res, err = red:get (key) if not res or res = = Ngx.null then return end Ngx.var.conta Iner_url = res returnend--save found key to local cache for 5 Secondscache:set (host, RES, 5)//The mapping relationship in Redis is stored in the Redis Cache to avoid the next Redis operation Ngx.var.container_url = Res
It can be seen that the content of this project sharing, and unsatisfactory, but simply provide a way of thinking, how to achieve dynamic proxy_pass, on this basis we can carry on the extension of the URL rewrite. In addition, here the host corresponding to the routehost if only IP, then, will cause proxy_pass when the back end of a single point, that is, no application to upstream, no way to load balance. However, if the value of Routehost is upstream, then, in the configuration file, still write dead, so there is no way to achieve a full sense of dynamic routing.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

The above describes the Nginx_lua case analysis: Dynamic routing implementation, including the aspects of the content, I hope that the PHP tutorial interested in a friend helpful.

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.