First things first. I'm sorry for my bad english.
Hi guys.
I am using Lazarus/Free pascal at my Master Degree work, coding a multithread application for accelarate some things etc... Well, one part of this work involve (maybe in the future) a application running in multiple computers at the same time like distributed computing.
So, for this I' m working in a High Performance HTTP Server/JSON WebService with load balance, and maybe I' ll publish this somewhere (Like SourceForge) when I finish a beta version or whatever, but I' m not pretty sure if this is good enough or someone will be use. So I' ll put some code/ideas here about this project and please be free to comment.
Done
1- HTTP Server (Single Thread, Multi Threaded and Pool of Threads)
2- Advanced Route resolutions (With url params, fixed params and without params)
3- RPC JSON
4- Pool of Connections (SQLdb)
5- Thread Manager to create and destroy threads dynamically
6- Custom Exception Class (Webservice and RPC)
7- Load Balance with group of servers (We can define a group of servers to process one or more specific methods of webservice)
I' m working now
1- HTTPS Server
2- Pool of connection (ZeosLib)
3- Add and Remove servers from load balance in runtime.
To do
1- Better options to load balance
2- RPC JSON with HTTP (I' m using only TCP)
3- More optimizations in assembly/SIMD
Well, here it's a sample code about a function add two numbers
// First we need register the route
//Variable types string, integer and double is accepted, I' m still working in other types
WSAppRoute.AddRoute('api/math/add/@Integer;@Integer',@FuncAdd,[wsGet]);
// Second is the function
function FuncAdd(AData: string; AMethod: THTTPRequisition; AParams: TStringList; ANumber1, ANumber2: Integer): string;
begin
// Always will be wsGet because I don't put other option together, if the server receive a wsPost in this case, a code error 404 will be returned
if AMethod = wsGet then
begin
Result := IntToStr(ANumber1 + ANumber2);
end;
end;
// After
Server := THTTPServer.Create(8080);
Server.Active := True;
Call example
URL: localhost:8080/api/math/add/80&20
Result: 100
URL: localhost:8080/api/math/add/Hi&20
Result: Error 404
URL: localhost:8080/api/math/add/100&20
Result: 120
URL: localhost:8080/api/math/sub/100&20
Result: Error 404
About RPC Module, here is a simple example. (Server side)
TMathAdd = class(Tobject)
private
public
published
procedure Invoke;
property Number1: Integer;
property Number2: Integer;
property Result: Integer;
end;
procedure TMathAdd.Invoke;
begin
FResult := FNumber1 + FNumber2;
end;
// Register the class
Server := TRPCJSONServer.Create;
Server.AddMethod(TMathAdd);
Server.PortNumber := 6900;
Server.StartServer;
Client Side
var
Method: TRPCJSONClient;
Error: Boolean;
Message: string;
JReturn: TJSONData;
begin
Method := TRPCJSONClient.Create('write.the-rpc-server.here',6900);
Message := EmptyStr;
JReturn := Nil;
try
JReturn := Method.ExecuteMethod('MathAdd',[100,63],Method.NewID,Error);
ShowMessage(JReturn.AsJson);
except
on E: Exception do begin
Message := E.Message;
end;
end;
This code above will return 163. The prototype of function ExecuteMethod is
function ExecuteMethod(AMethod: string; const AArgs: array of const; AID: Integer; out AError: Boolean): TJSONData;
The server side is prepared to response cases below.
1) Sucess
{"jsonrpc": "2.0", "result": 163, "id": 1}
or
2) Error
-32700 Parse error
-32600 Invalid Request
-32601 Method not found
-32602 Invalid params
-32603 Internal error
-32000 to -32099 Server error
According
http://www.jsonrpc.org/specificationSo, later I' ll put others examples with load balance.
Cya