You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
6.6 KiB
205 lines
6.6 KiB
1 month ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System.Threading.Tasks;
|
||
|
using System.Threading;
|
||
|
|
||
|
using Sog;
|
||
|
using SimpleHttpServer;
|
||
|
|
||
|
namespace Operation
|
||
|
{
|
||
|
internal class HttpRequestInfo
|
||
|
{
|
||
|
public HttpContext Http;
|
||
|
public DateTime BeginTime;
|
||
|
public bool StartProcess;//是否开始处理
|
||
|
public bool ProcessEnd; //是否处理完毕
|
||
|
public int ProcessResult; //错误码
|
||
|
}
|
||
|
|
||
|
/// 同步模式的http服务器
|
||
|
/// 异步模式,处理消息是多线程
|
||
|
/// 同步模式,处理消息是单线程,并且需要主动调用update处理
|
||
|
public class SyncHttpServerService
|
||
|
{
|
||
|
private object m_locker ;//锁
|
||
|
|
||
|
private HttpServer m_server;
|
||
|
private int m_timeoutMs;
|
||
|
|
||
|
//保存的外部的回调处理器
|
||
|
private Action<HttpContext> m_outCallable;
|
||
|
|
||
|
internal List<HttpRequestInfo> m_requestList = new List<HttpRequestInfo>();
|
||
|
List<HttpRequestInfo> m_updateRequestList = new List<HttpRequestInfo>();
|
||
|
|
||
|
public void StartHttpServer(int port, Route routeConfig, int timeout = 5000)
|
||
|
{
|
||
|
m_locker = new object();//锁
|
||
|
|
||
|
m_timeoutMs = timeout;
|
||
|
m_outCallable = routeConfig.Callable;
|
||
|
routeConfig.Callable = this.HttpRequestCallback;
|
||
|
|
||
|
List<Route> listconfig = new List<Route>();
|
||
|
|
||
|
listconfig.Add(routeConfig);
|
||
|
|
||
|
m_server = new HttpServer(port, listconfig);
|
||
|
Thread thread = new Thread(new ThreadStart(m_server.Listen));
|
||
|
thread.IsBackground = true;//设置成后台线程,如果不是后台线程,线程不是主动关闭,则会一直运行,那怕进程主线程退出也没用
|
||
|
thread.Start();
|
||
|
|
||
|
TraceLog.Debug("SyncHttpServerService.StartHttpServer listen on {0}", port);
|
||
|
}
|
||
|
|
||
|
private void HttpRequestCallback(HttpContext httpContext)
|
||
|
{
|
||
|
//停服不允许访问
|
||
|
if(OperationServerUtils.GetApp().IsStopping)
|
||
|
{
|
||
|
httpContext.httpResponse = new HttpResponse
|
||
|
{
|
||
|
ContentAsUTF8 = "server stop",
|
||
|
ReasonPhrase = "Forbidden",
|
||
|
StatusCode = "403"
|
||
|
};
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
DateTime beginTime = DateTime.Now;
|
||
|
bool bTimeout = false;
|
||
|
|
||
|
HttpRequestInfo info = new HttpRequestInfo();
|
||
|
info.Http = httpContext;
|
||
|
info.BeginTime = beginTime;
|
||
|
info.ProcessEnd = false;
|
||
|
|
||
|
lock (m_locker)
|
||
|
{
|
||
|
m_requestList.Add(info);
|
||
|
}
|
||
|
|
||
|
//等待处理结束
|
||
|
while(true)
|
||
|
{
|
||
|
if (info.ProcessEnd == true)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//对于http请求来说10毫秒足够了
|
||
|
Thread.Sleep(10);
|
||
|
|
||
|
//判断超时
|
||
|
if ((DateTime.Now - beginTime).TotalMilliseconds >= m_timeoutMs)
|
||
|
{
|
||
|
TraceLog.Error("SyncHttpServerService.HttpRequestCallback request method {0} url {1} timeout!", httpContext.httpRequest.Method, httpContext.httpRequest.Url);
|
||
|
bTimeout = true;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lock (m_locker)
|
||
|
{
|
||
|
m_requestList.Remove(info);
|
||
|
}
|
||
|
|
||
|
//超时
|
||
|
if (bTimeout)
|
||
|
{
|
||
|
httpContext.httpResponse = new HttpResponse
|
||
|
{
|
||
|
ContentAsUTF8 = "timeout",
|
||
|
ReasonPhrase = "InternalServerError",
|
||
|
StatusCode = "500"
|
||
|
};
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//出错,比如处理过程异常
|
||
|
if(info.ProcessResult != 0)
|
||
|
{
|
||
|
httpContext.httpResponse = new HttpResponse
|
||
|
{
|
||
|
ContentAsUTF8 = "error",
|
||
|
ReasonPhrase = "InternalServerError",
|
||
|
StatusCode = "500"
|
||
|
};
|
||
|
}
|
||
|
//成功
|
||
|
else
|
||
|
{
|
||
|
httpContext.httpResponse = info.Http.httpResponse;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!httpContext.httpResponse.Headers.ContainsKey("Content-Type"))
|
||
|
{
|
||
|
httpContext.httpResponse.Headers["Content-Type"]="application/json; charset=utf-8";
|
||
|
}
|
||
|
|
||
|
HttpServer.SendResponse(httpContext);
|
||
|
}
|
||
|
|
||
|
//同步调用
|
||
|
public void Update()
|
||
|
{
|
||
|
DateTime beginTime = DateTime.Now;
|
||
|
|
||
|
//申请一个临时数组,这样可以避免循环过程中加锁
|
||
|
m_updateRequestList.Clear();
|
||
|
|
||
|
lock (m_locker)
|
||
|
{
|
||
|
m_updateRequestList.AddRange(m_requestList);
|
||
|
}
|
||
|
|
||
|
int iCount = 0;
|
||
|
foreach(HttpRequestInfo requestInfo in m_updateRequestList)
|
||
|
{
|
||
|
if(requestInfo.StartProcess == false)
|
||
|
{
|
||
|
requestInfo.StartProcess = true;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
//HttpContext hc = new HttpContext(null);
|
||
|
//hc.httpRequest = requestInfo.Request;
|
||
|
m_outCallable(requestInfo.Http);
|
||
|
|
||
|
//不需要等待时退出
|
||
|
if (!requestInfo.Http.httpResponse.IsWaitFor)
|
||
|
{
|
||
|
requestInfo.ProcessEnd = true;
|
||
|
}
|
||
|
}
|
||
|
catch(Exception ex)
|
||
|
{
|
||
|
requestInfo.ProcessEnd = true;
|
||
|
requestInfo.ProcessResult = -1;
|
||
|
|
||
|
TraceLog.Exception(ex);
|
||
|
TraceLog.Error("SyncHttpServerService.Update request method {0} url {1} process error!"
|
||
|
, requestInfo.Http.httpRequest.Method, requestInfo.Http.httpRequest.Url);
|
||
|
}
|
||
|
|
||
|
iCount++;
|
||
|
}
|
||
|
|
||
|
//一次循环最多花100毫秒时间,超过了下次tick再处理
|
||
|
if ((DateTime.Now - beginTime).TotalMilliseconds >= 100)
|
||
|
{
|
||
|
TraceLog.Error("SyncHttpServerService.Update process request too slow, count {0} in this update, start {1} now {2}"
|
||
|
, iCount, beginTime.ToString("HH:mm:ss.fff"), DateTime.Now.ToString("HH:mm:ss.fff"));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|