一、场景概述
近期业务应用过程当中,需要对不同的类型进行分流转发,实现的总体方向是将原有的免费的内容进行付费改造。经过业务讨论,实现方案有两种。
第一种方案:直接采用微信、今日头条、抖音、百度百家号等平台的付费专栏实现,或者采用短书等知识付费平台实现。
第二种方案:在第一种思路的基础上,自研发付费阅读平台。
在以上两种方案实施过程当中面临一个问题需要解决,付费内容实现后,部分原有的免费资源如何跳转到付费的平台。同一个资源不能既免费又付费,这存在问题。
二、解决思路
1、第一阶段思考:将免费的内容从原有的平台人工去除或者隐藏,但涉及多个平台多个部门一时间无法解决。
2、第二阶段思考:能否通过技术手段将免费的内容跳转到付费平台,于是自研付费阅读平台,然后提供API接口。
3、第三阶段思考:通过网关层对内容进行判断,先调用API判断是否为付费,如付费将流量分发至付费平台,其它的正常免费浏览。
4、第四阶段思考:实现网关层的思路有在程序层面进行处理,但由于原资源为静态页面,不能通过动态程序实现。此时想到了从HTTP协议层来进行处理,根据HTTP协议首先对请求的头部判断,然后做后续的逻辑处理。
5、第五阶段思考:最终从HTTP中间件层想到了解决方案,开源的nginx和apache等,可以进行二次开发来解决。从应用的实际情况,选择了通过nginx二次开发的方案来解决。
6、第六阶段思考:nginx二次开发可以直接通过开发nginx子模块的形式,但要对C,C++编程有比较高的要求。通过对官方文档的阅读,发现了Lua的集成版本Openresty。通过一个简单的二次开发即可解决此分流方式。
三、解决过程
1、搭建环境,直接上官方网站Openresty编译环境安装和配置即可。(此部分比较简单)
2、对nginx的请求执行流程要比较清楚,可以参考大量的nginx的二次开发的书籍。
3、直接上代码:
local cjson = require "cjson"
local uri = ngx.var.request_uri
local server_name = ngx.var.server_name
if not server_name == "abc.com" then
return
end
local http = require "resty.http"
local httpc = http.new()
local apiUrl = "http://abcd.com/api.php"
local res,err = httpc:request_uri(apiUrl,{
method = "POST",
body = "url=http://abc.com"..uri,
headers = {["Content-Type"] = "application/x-www-form-urlencoded",},
keepalive_timeout = 60,
keepalive_pool = 10
})
if not res then
ngx.say("failed to request: ", err)
return
end
local data = cjson.decode(res.body)
if (data.payurl == nil or data.payurl == '') then
return
else
return ngx.redirect(data.payurl,302)
end
以上代码只进行了核心功能的实现,基本上已经可以满足生产环境的使用了。但代码还有比较大的优化空间,如对安全性、异常等的处理。
四、总结
1、nginx+lua的解决方案在现在的互联网上应用非常广泛,只需要非常精简的Lua代码即可解决问题。在实现过程中要特别注意nginx的请求处理流程,需要认真的研究其源代码。
2、实现的思路还有很多,如node.js等,最终的原理都是从网关层进行处理。