这里的路由指的是在web开发中,访问路径以及具体实现内容的映射。比如,/a映射到某个具体的页面,这个就称之为一个路由。而动态路由,顾名思义就是动态添加这种路由映射关系。
在nginx中,通过rewrite和proxy_pass来实现路由映射或者说反向代理,但是这种关系按照传统的配置必须写死在配置文件中,然后通过快速"无缝"重启nginx。虽说是无缝,但是其繁琐的配置和枯燥的重启操作还是无法避免。
最近,在github上看到个项目ceryx,是nginx结合lua进行动态路由的映射的,也就是上面所说的映射关系,用lua来管理,虽然是比较简单的实现,但是可以分析学习下。该项目通过用redis的
from ceryx.db import RedisRouter resource_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(source): """ 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='Route with source {} doesn\'t exist'.format(source) ) class Route(Resource): """ Resource describing a single Route. 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
上述的代码,是进行路由管理的http api,当然,这个不是我们分析的重点。先来看一下,在这个项目里面,对nginx的配置是怎样的
upstream fallback { server www.something.com; } server { listen 80; default_type text/html; location / { set $container_url "fallback"; resolver 8.8.8.8; # Lua files access_by_lua_file lualib/router.lua;//切入点 # 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+(/.+)$ $2; 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; } ... }可以简单的看到,这个配置相当的常见,跟普通的反向代理并没有什么不同,真正的切入点在于access_by_lua_file里面的router.lua代码。
local container_url = ngx.var.container_url//拿到配置文件中的container_url local host = ngx.var.host //拿到请求的时候的host,比如我们请求http://www.xxx.com/a.html 那这里的host就是www.xxx.com -- Check if key exists in local cache local cache = ngx.shared.ceryx local res, flags = cache:get(host) //直接在nginx cache中拿host对应的路由映射,如果存在则直接返回结果 if res then ngx.var.container_url = res return end local redis = require "resty.redis" // redis的连接代码 每次都会连接redis, local red = redis:new()<span style="white-space:pre"> </span>//<span style="font-family: Arial, Helvetica, sans-serif;">这个操作比较相对比较耗时 所以接下来的操作才会在本地cache中存对应的关系</span> red:set_timeout(100) -- 100 ms local redis_host = os.getenv("CERYX_REDIS_HOST") if not redis_host then redis_host = "127.0.0.1" end local redis_port = os.getenv("CERYX_REDIS_PORT") if not redis_port then redis_port = 6379 end local res, err = red:connect(redis_host, redis_port) -- Return if could not connect to Redis if not res then return end -- Construct Redis key local prefix = os.getenv("CERYX_REDIS_PREFIX") if not prefix then prefix = "ceryx" end local key = prefix .. ":routes:" .. host -- Try to get target for host res, 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.container_url = res return end -- Save found key to local cache for 5 seconds cache:set(host, res, 5) // 在redis取出的映射关系存到redis的cache中避免下次继续连redis操作 ngx.var.container_url = res可以看出,这个项目分享的内容,并不尽人意,只是简单的提供了一种思路,如何去实现动态的proxy_pass,在这个基础上我们可以进行对url rewrite的扩展。另外,这里的host对应的routeHost 如果只是IP,那样的话,会造成proxy_pass的时候后端的单点,也就是没有应用到upstream,没办法进行负载均衡。但是如果routeHost的值是upstream的话,则,在配置文件中,依然要写死,所以,没有办法做到完全意义上的动态路由。
版权声明:本文为博主原创文章,未经博主允许不得转载。
以上就介绍了nginx_lua案例分析:动态路由实现,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

Redis是现在最热门的key-value数据库,Redis的最大特点是key-value存储所带来的简单和高性能;相较于MongoDB和Redis,晚一年发布的ES可能知名度要低一些,ES的特点是搜索,ES是围绕搜索设计的。

相信很多朋友在Windows下都习惯用SourceInsight来阅读分析源代码了,对于LINUX下面的工具,确实有比较高效的,配置起来起对比较麻烦,也比较繁琐,相信很多人肯定希望能在Linux下面也能用到SourceInsight,下面小编将为大家带来Ubuntu中SourceInsight的使用详解!一起去看看吧!这是我的系统信息:Linuxgavin-laptop2.6.32-40-generic#87-UbuntuSMPTueMar600:56:56UTC2012x86_64GNU/Li

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于redis的一些优势和特点,Redis 是一个开源的使用ANSI C语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式存储数据库,下面一起来看一下,希望对大家有帮助。

source是切换输入信号源或选择不同的输入源的按键。通常出现在电视、投影仪、音响系统、电脑显示器等设备上。在电视上,source按键可以让用户切换不同的输入源,从而在电视上播放不同的内容。在投影仪上,source按键的作用类似,可以将不同的设备连接到投影仪上。在音响系统上,source按键用于切换不同的音频输入源。在电脑显示器上,source按键的作用与电视和投影仪类似等等。

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis Cluster集群收缩主从节点的相关问题,包括了Cluster集群收缩概念、将6390主节点从集群中收缩、验证数据迁移过程是否导致数据异常等,希望对大家有帮助。

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于原子操作中命令原子性的相关问题,包括了处理并发的方案、编程模型、多IO线程以及单命令的相关内容,下面一起看一下,希望对大家有帮助。

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了bitmap问题,Redis 为我们提供了位图这一数据结构,位图数据结构其实并不是一个全新的玩意,我们可以简单的认为就是个数组,只是里面的内容只能为0或1而已,希望对大家有帮助。

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于实现秒杀的相关内容,包括了秒杀逻辑、存在的链接超时、超卖和库存遗留的问题,下面一起来看一下,希望对大家有帮助。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

禅工作室 13.0.1
功能强大的PHP集成开发环境

SublimeText3汉化版
中文版,非常好用

SublimeText3 Linux新版
SublimeText3 Linux最新版

记事本++7.3.1
好用且免费的代码编辑器

Dreamweaver CS6
视觉化网页开发工具