159 lines
4.7 KiB
Lua
159 lines
4.7 KiB
Lua
local skynet = require "skynet"
|
||
local socket = require "skynet.socket"
|
||
local httpd = require "http.httpd"
|
||
local sockethelper = require "http.sockethelper"
|
||
local urllib = require "http.url"
|
||
local serverId = tonumber(skynet.getenv "serverId")
|
||
|
||
local log = require "Log"
|
||
local table = table
|
||
local string = string
|
||
local mode, protocol = ...
|
||
protocol = protocol or "http"
|
||
|
||
if mode == "agent" then
|
||
local function response(id, write, ...)
|
||
local headers =
|
||
{
|
||
['Access-Control-Allow-Origin'] = '*', -- 这里写允许访问的域名就可以了,允许所有人访问的话就写*
|
||
['Access-Control-Allow-Credentials'] = true,
|
||
}
|
||
local code, tmp = ...
|
||
local ok, err = httpd.write_response(sockethelper.writefunc(id),code,tmp,headers)
|
||
if not ok then
|
||
skynet.error(string.format("fd = %d, %s", id, err))
|
||
end
|
||
end
|
||
|
||
local SSLCTX_SERVER = nil
|
||
local function gen_interface(protocol, fd)
|
||
if protocol == "http" then
|
||
return {
|
||
init = nil,
|
||
close = nil,
|
||
read = sockethelper.readfunc(fd),
|
||
write = sockethelper.writefunc(fd),
|
||
}
|
||
elseif protocol == "https" then
|
||
local tls = require "http.tlshelper"
|
||
if not SSLCTX_SERVER then
|
||
SSLCTX_SERVER = tls.newctx()
|
||
-- gen cert and key
|
||
-- openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -out server-cert.pem
|
||
local certfile = skynet.getenv("certfile") or "./server-cert.pem"
|
||
local keyfile = skynet.getenv("keyfile") or "./server-key.pem"
|
||
print(certfile, keyfile)
|
||
SSLCTX_SERVER:set_cert(certfile, keyfile)
|
||
end
|
||
local tls_ctx = tls.newtls("server", SSLCTX_SERVER)
|
||
return {
|
||
init = tls.init_responsefunc(fd, tls_ctx),
|
||
close = tls.closefunc(tls_ctx),
|
||
read = tls.readfunc(fd, tls_ctx),
|
||
write = tls.writefunc(fd, tls_ctx),
|
||
}
|
||
else
|
||
error(string.format("Invalid protocol: %s", protocol))
|
||
end
|
||
end
|
||
skynet.start(function()
|
||
skynet.dispatch("lua", function (_,_,id,addr)
|
||
socket.start(id)
|
||
local interface = gen_interface(protocol, id)
|
||
if interface.init then
|
||
interface.init()
|
||
end
|
||
-- limit request body size to 8192 (you can pass nil to unlimit)
|
||
local code, url, method, header, body = httpd.read_request(interface.read, 8192)
|
||
log.info("HttpServer收到消息",addr,code, url, body)
|
||
|
||
--每次只找最后参数
|
||
local str = url
|
||
local subStr = "/"
|
||
local lastIndex = string.find(str, subStr) -- 返回第一次出现subStr的索引值
|
||
while true do
|
||
local nextIndex = string.find(str, subStr, lastIndex + 1) -- 从上一次结果之后开始查找
|
||
if not nextIndex then break end -- 如果没有再找到则退出循环
|
||
lastIndex = nextIndex -- 更新lastIndex为当前找到的索引值
|
||
end
|
||
url = string.sub(str , lastIndex + 1 , #str)
|
||
log.debug("HttpServer截取Url后的值" , url )
|
||
|
||
if code then
|
||
if code ~= 200 then
|
||
response(id, interface.write, code)
|
||
else
|
||
local RecvMsg = {}
|
||
--把消息转向主服务器
|
||
local s2cData,retLen = skynet.call("StartServer", "lua","HttpMsg",id ,url , body , addr, header)
|
||
if s2cData then
|
||
--if "metrics" == url or "health" == url then
|
||
-- RecvMsg = s2cData
|
||
--else
|
||
table.insert(RecvMsg,s2cData.."\n")
|
||
RecvMsg =table.concat(RecvMsg,"\n")
|
||
--end
|
||
end
|
||
response(id, interface.write, code, RecvMsg )
|
||
end
|
||
else
|
||
if url == sockethelper.socket_error then
|
||
skynet.error("socket closed")
|
||
else
|
||
skynet.error(url)
|
||
end
|
||
end
|
||
|
||
--该接口传输大量数据时,有可能未传完,socket就关闭了,对其进行sleep 1000ms 后再关闭socket。
|
||
if "QueryClusterInfo" == url then
|
||
skynet.sleep(100)
|
||
end
|
||
|
||
log.info("关闭SOCKET", id , url)
|
||
socket.close(id)
|
||
if interface.close then
|
||
interface.close()
|
||
end
|
||
end)
|
||
end)
|
||
else
|
||
local agent = {}
|
||
local balance = 1
|
||
skynet.start(function()
|
||
skynet.dispatch("lua", function (_,_, cmd, ...)
|
||
if "Post" == cmd then
|
||
log.info("cmd",cmd ,...)
|
||
local id , interface, code,tmp = ...
|
||
if "write" == interface then
|
||
response(id, interface.write, code, tmp)
|
||
end
|
||
end
|
||
end)
|
||
end)
|
||
|
||
local serverIp , serverPort = ...
|
||
skynet.start(function()
|
||
local protocol = "http"
|
||
|
||
--游戏服只需要5个 http agent就够
|
||
local agentCount = 100
|
||
if serverId >= 100 then
|
||
agentCount = 5
|
||
end
|
||
|
||
for i= 1, agentCount do
|
||
agent[i] = skynet.newservice(SERVICE_NAME, "agent", protocol)
|
||
end
|
||
|
||
local id = socket.listen( serverIp , serverPort)
|
||
skynet.error(string.format("服务器 %s 监听端口 %s 协议 %s", serverIp ,serverPort , protocol))
|
||
socket.start(id , function(id, addr)
|
||
skynet.error(string.format("%s connected, pass it to index %d agent :%08x", addr,balance, agent[balance]))
|
||
skynet.send(agent[balance], "lua", id , addr )
|
||
balance = balance + 1
|
||
if balance > #agent then
|
||
balance = 1
|
||
end
|
||
end)
|
||
end)
|
||
end |