我试图在NodeJs中使用C#实现http服务器。 在NodeJs中,我实现了异步http服务器,如下所示。
var config = require('./config'),
cluster = require('cluster'),
dgwLogger = require('./modules/dgwLogger'),
healthChecker = require('./modules/healthChecker'),
crashLogger = require('./modules/crashLogger');
module.exports = exports = getWorkerID = function() {
return cluster.worker === null ? 0 : cluster.worker.id;
}
if (config.useCluster && cluster.isMaster) {
var cpuNum;
if (typeof config.useCluster === 'number')
cpuNum = config.useCluster;
else
cpuNum = require('os').cpus().length;
for (var i = 0; i < cpuNum; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
cluster.fork();
});
} else {
var express = require('express'),
http = require('http'),
var app = express();
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(sendResJson);
app.use(express.errorHandler());
app.post("/auth/getPJCharacter", gameServer.getPJCharacter);
app.post("/auth/addPJCharacter", gameServer.addPJCharacter);
setTimeout(function() {
http.createServer(app).listen(config.pjoa.port, function() {
checkHealth();
});
}, 1000);
}
代码根据cpu计数创建所有线程,express模块监听单个端口。每当有来自端口的请求时,集群就会自动向单独的线程发送请求。 我听说这种方法可以有效地处理多个请求。但是现在,我在客户端使用C#,所以我也希望使用服务器端语言作为C#,因为我做了一个人项目,并且在服务器之间使用不同的语言很难和客户。 以下代码是C#版本。
class Program{
static void Main (string[] args){
WebServerMain main = new WebServerMain ();
main.Init ();
}
}
public class WebServerMain{
private static WebServerMain singleton;
public static WebServerMain Instance{
get{
return singleton;
}
}
const int MAX_WORKERS = 2;
AsyncHttpServer[] threadList = new AsyncHttpServer[MAX_WORKERS];
public MySqlTest SqlManager;
public MemAccessor MemManager;
public TGBaseData BaseData;
public WebServerMain (){}
public void Init(){
singleton = this;
SqlManager = new MySqlTest ();
MemManager = new MemAccessor ();
MemManager.Init ();
BaseData = new TGBaseData ();
BaseData.Load ();
for (int i = 0; i < MAX_WORKERS; i++) {
threadList [i] = new AsyncHttpServer ();
threadList[i].ID = i;
}
StartLoop ();
}
public void StartLoop(){
HttpListener listener = new HttpListener ();
listener.Prefixes.Add("http://*:8081/");
listener.Start();
Console.WriteLine ("Server Started at localHost");
while (true) {
HttpListenerContext context = listener.GetContext();
AsyncHttpServer temp = GetLessWorkingThread ();
temp.QueueRequest (context);
}
}
AsyncHttpServer GetLessWorkingThread(){
int index = 0;
int min = 1000000000;
for (int i = 0; i < threadList.Length; i++) {
if (threadList [i].TotalProcessing < min) {
min = threadList [i].TotalProcessing;
index = i;
}
}
return threadList [index];
}
}
public class AsyncHttpServer
{
public int ID;
public int TotalProcessing;
//Queue
MarshalSyncContext curSyncContext;
Queue<HttpListenerContext> contextQueue;
Thread loopThread;
Dictionary<int,HttpListenerContext> contextDic;
Dictionary<string,ServiceTaskDelegate> serviceDic;
public AsyncHttpServer (){
contextDic = new Dictionary<int, HttpListenerContext> ();
contextQueue = new Queue<HttpListenerContext> ();
serviceDic = new Dictionary<string,ServiceTaskDelegate> ();
MainLoginService.AddService (serviceDic);
ThrowGameMainService.AddService (serviceDic);
loopThread = new Thread (DoListeningWork);
loopThread.Start ();
}
public void QueueRequest(HttpListenerContext context){
TotalProcessing++;
contextQueue.Enqueue (context);
}
void DoListeningWork(){
curSyncContext = new MarshalSyncContext ();
while (true) {
if (contextQueue.Count > 0) {
HttpListenerContext context = contextQueue.Dequeue ();
// Console.WriteLine ("Context=" + context.GetType ().ToString ());
Task req = ProcessRequest (context);
contextDic.Add (req.Id, context);
req.ContinueWith (task => {
TotalProcessing--;
HttpListenerContext tempContext = contextDic[ task.Id ];
contextDic.Remove(task.Id);
if(task.IsFaulted == true){
task.Exception.Handle( exception =>{
Console.WriteLine(exception.Message);
Console.WriteLine(exception.StackTrace);
return true;
});
XElement temp = new XElement("Root",
new XElement("Err",Err.INTERNAL_ERROR));
WriteSimpleText(tempContext, temp.ToString());
tempContext.Response.Close();
}
});
}
curSyncContext.ProcessAwaitProcedures ();
Thread.Sleep (1000);
}
}
在AsyncHttpServer类中,类生成单个线程并检查从WebServerMain循环给出的队列数据。但是在等待队列时,我使用while(true)等待队列,但是这使得该程序的结果在完整的CPU资源中运行。 (如果我设置4个多线程,那么它使用400%的CPU)。 每当有请求时我都尝试创建Task线程,但这会产生太多线程,所以我不得不使用这个方法。 有没有办法不使用完整的CPU? 或者这是实现像NodeJS http服务器一样的异步Http服务器的正确方法吗?