You are not logged in.
Hi, is it possible to change the queue length? It seems that if the api server's OnRequest() took too long to process, and the incoming queue got filled up to 1000, the next incoming connection will get a 503 error. Under IIS there is an option to change the queue length ("kernel request limit" in IIS6) for a particular application pool (default is 1000), but is there any option to change it under http api server? Thx.
Offline
This option sounds to be available in HTTP API 2.0
http://msdn.microsoft.com/en-us/library … s.85).aspx
And perhaps HTTP API 1.0
http://msdn.microsoft.com/en-us/library … s.85).aspx
and
http://msdn.microsoft.com/en-us/library … s.85).aspx
But both are time out values, in time, not queue length.
I'm not sure those are the same than your IIS parameter.
Note that mORMot server uses a thread pool, so if one request takes long, the next is taken in account by another thread.
You can enhance the number of threads, if you are afraid of a 503 error.
But I did not see such issues in the wild, even with the current settings.
Offline
Thx, but I assume the thread pool is for THttpServer but not THttpAPIServer? I've just tried THttpServer and deliberately block OnRequest(), then make 1000 http connections to the server, and the thread count of the server is well over 1000.
The main problem for me is to handle a sudden burst of incoming connection, say > 20000 at the same time. There is no need to process all the request at the same time. Client can wait but should not return any error. One connection per thread is already out of the question. Http API can handle it since it has build-in kernel mode request queue. The queue length can be easily setup in IIS, but it seems there is no easy way to change the value using Http API 1.0 (THttpAPIServer).
Also, afaik, THttpAPIServer can only handle one single OnRequest() at a time. Http.ReceiveHttpRequest() is only called once in the main loop. If OnRequest() is blocked then other incoming connections have to be waited in the request queue until another Http.ReceiveHttpRequest() is called. If the request queue is full then the next client will get an instant 503 error. My idea is to call Http.ReceiveHttpRequest() multiple times and split those requests into different threads.
Offline
but I assume the thread pool is for THttpServer but not THttpAPIServer
Please, pay attention to THttpApiServer.Clone method. This one creates the thread pool. Each cloned thread registers itself to http.sys and then http.sys manages it in the similar way as HttpServer does. As far as I understand you overflow not length of queue, but time request wait in queue. So AB is right - increase thread pool size.
Offline
but I assume the thread pool is for THttpServer but not THttpAPIServer
Please, pay attention to THttpApiServer.Clone method. This one creates the thread pool. Each cloned thread registers itself to http.sys and then http.sys manages it in the similar way as HttpServer does. As far as I understand you overflow not length of queue, but time request wait in queue. So AB is right - increase thread pool size.
oops.... I've missed the .Clone() function (though it was for something else...). Thx a lot~
Offline
But still doesn't solve the queue length problem. Under a controlled stress test, the server takes 50ms to finish each request. I've set clone thread size to 256. A sudden burst of ~4000 incoming connection still return status 503 error half of the time.
Offline
What tool do you use to create such load? What OS is your server? May be you reached max number of socket? See here for example http://www.catalyst.com/kb/100072
Offline
Ups! We found queue problem during try to put into production system with 20 000 users.
It happens in the morning while all 20 000 users try to log-in to server in the nearly same time.
Also we found a way to reproduce it in synthetic test.
Under UNIX exist tool wrk. To reproduce problem we need to increase socket limit first.
# ulimit -n 10000
# ./wrk -c 10000 -t 10 -d 10s --latency http://mormotHTTPAPIserver/timeStamp
In the HTTP.sys error log we can see (normally here C:\Windows\System32\LogFiles\HTTPERR\ ) QueueFull error messages
To solve the problem we add HTTPAPI2.0 support to SynCrtSock.pas (via {$ifdef HTTPAPI20}) and add THttpApiServer.HTTPQueueLength property to change Queue length from default 1000 to any value.
Also we work on adding other HTTPAPI2.0 features (mostly QoS we need).
AB - I send to you version with HTTPQueueLength.
Note - HTTPAPI2.0 requirements:
- Minimum supported client Windows Vista
- Minimum supported server Windows Server 2008
Offline
That's it.
I've included your great proposal.
See http://synopse.info/fossil/info/9ddf00210f
Thanks a lot for your feedback and code patch!
We all hope that the situation in your country will stabilize and be as peaceful as possible.
Offline
http.sys kernel-mode server handles HTTP API 2.0 (available since Windows Vista / Server 2008), or fall back to HTTP API 1.0 (for Windows XP or Server 2003).
Thanks to this fall-back mechanism, there is no need of any conditional definition now: the class will use the highest API available.
We also included several fixes after further testing of the initial implementation (e.g. when serving multi TSQLRestServerDB instance).
Offline
I don't understand.
If I update my framework version with this last version, my application will be problem to run on Windows XP by default?
I need to run my application on Windows XP, Vista, 7 and 8, can I update the framework? Do I need change my code?
Thanks
Offline
Nothing to change.
The correct API will be recognized automatically.
So any existing code will work for XP or VISTA and up, with no modification.
Only the THttpApiServer.ServerQueueLength property will work only for Vista/2003 and up.
You can use this property as such:
if aSQLHttpServer.HttpServer.InheritsFrom(THttpApiServer) then
THttpApiServer(aSQLHttpServer.HttpServer).HTTPQueueLength := 5000;
Offline
AB, in http://synopse.info/fossil/info/1eda390096 SynCrtSock commit there is issue (from my POW) in THttpApiServer.SetHTTPQueueLength.
We have one fReqQueue for all cloned thread, so we do not need to call SetHTTPQueueLength for all cloned thread. So, last circle is overhead....
See ticket http://synopse.info/fossil/tktview?name=51a9c086f3
Last edited by mpv (2014-03-13 08:30:27)
Offline
Indeed!
Thanks for the input.
Offline
AB, from my production statistic I have near 1 million server request during workday. To each response we add 45 bytes ("X-Powered-By: SynCrtSock http://synopse.info") header . This create additional 45MBytes/day traffic . From protocol POW we can use "Server:" header instead. http://www.w3.org/Protocols/rfc2616/rfc … l#sec14.38. I add
const
respServerHeader: PAnsiChar = 'mORMot';
....
procedure THttpApiServer.Execute;
......
// send response
Resp^.Version := Req^.Version;
with Resp^.Headers.KnownHeaders[respServer] do begin
pRawValue := respServerHeader;
RawValueLength := length(respServerHeader);
end;
and remove adding of X-Powered-By in HTTP_RESPONSE.SetHeaders
After this I got headers in response:
Server: mORMot Microsoft-HTTPAPI/2.0
(I can't found how to disable adding of 'Microsoft-HTTPAPI/2.0' - HTTP.sys add it automatically)
instead of
Server: Microsoft-HTTPAPI/2.0
X-Powered-By: SynCrtSock http://synopse.info
minus 40 bytes
If You decide to apply this patch it will be VERY good to give other developer ability to redefine respServerHeader. May be by add property ServerSoftwareName to THttpApiServer?
I create feature request http://synopse.info/fossil/tktview?name=f4a68b1431
Last edited by mpv (2014-03-15 11:23:08)
Offline
You are welcome!
Thanks for taking the time to close all fixed tickets.
This is nice seeing that mORMot's quality is always increasing, and able to serve million requests per days, with high number of concurrent connections!
Mainly thanks to feedback like yours!
We also hope that peace will stay in your country.
Offline
AB, I patch constructor THttpApiServer.Create a little bit - now it allow Queue monitoring via Perfmon "HTTP Services Requests Queue" counter. In prev. version we create queue without name, and such queue not visible in counters. Please, modify:
constructor THttpApiServer.Create(CreateSuspended: Boolean);
var bindInfo: HTTP_BINDING_INFO;
serverSessionStr: WideString;
....
serverSessionStr := UIntToStr(fServerSessionID);
EHttpApiServer.RaiseOnError(hCreateRequestQueue,Http.CreateRequestQueue(
Http.Version,pointer(serverSessionStr),nil,0,fReqQueue));
P.S. Already forgot how to work with fossill
Offline
Offline
AB, ServerSessionID actually is Int64. In my implementation I use UIntToStr(ServerSessionID) since in XE2 I have overload UIntToStr(Value: UInt64). In your implementation we lost some bytes (direct convertion to Cardinal) and as result it is possible to have collision in QueueName. HTTPAPI don't allow to create two queue with the same name - so it is possible situation I can't create two instance of THttpApiServer. May be add StrInt64 from SynCommons to SynCtrlSock and use it?
Last edited by mpv (2014-03-20 07:21:03)
Offline
You are right.
Identifier to the HTTP API 2 session is now encoded as hexadecimal text (to avoid any collision error).
See http://synopse.info/fossil/info/05e0031069
Offline
We add some QoS ability to HTTP API 2 based server:
MaxConnections - The maximum number of HTTP connections allowed
MaxBandwidth - The maximum allowed bandwidth rate in bytes per second
MaxConnections is tested and work perfect. MaxBandwidth is actually change HTTP API value, but download speed remain the same May be this is my OS limitation (Windows 8 Home)..
AB, I send you patched sources.
Offline
We have added THttpApiServer.MaxBandwidth and THttpApiServer.MaxConnections properties (for HTTP API 2.0 only)...
See http://synopse.info/fossil/info/4e61734d33
Thanks mpv for the proposal and code patch!
Offline
Arnaud/mpv, would it be possible to publish fServerSessionID and fUrlGroupID as public read-only properties? I have patched my code, but would be great if it is in the official source to make it easier for me to update sources.
The reason the properties are useful is that I need to query the performance stats within the programme itself... or did I miss something?
Thanks!
Offline
Good idea.
I've added THttpApiServer.ServerSessionID and UrlGroupID read-only properties.
See http://synopse.info/fossil/info/1101f033bb
Thanks for the feedback.
If you have any code to propose, feel free!
Offline
A quick one... ULONGLONG should be UInt64 and not Int64?
Offline
And thanks for the prompt response Arnaud!
Offline
A quick one... ULONGLONG should be UInt64 and not Int64?
AFAIK yes, it should.
"U" stands for "U"nsigned... But it won't matter much, in all cases (on older versions of Delphi, there is no QWord/UInt64, just plain signed Int64, and it works!)...
Offline
Line 844 of SynCrtSock.pas
ULONGLONG = Int64;
Should it be
ULONGLONG = UInt64;
instead?
Update: Oops sorry, did not notice your reply. Yea it works if we convert it to Hex. It only fails to work if we print out the value as integer.
Last edited by cheemeng (2014-04-08 04:50:13)
Offline