Ssrc Web Wispers™ Distributed service-oriented Web development framework

Software icon

Ssrc Web Wispers™ allows you to rapidly build scalable Web applications to be deployed on a cluster or wide-area network. In today's parlance, Web Wispers™ enables small to medium-scale cloud computing (up to 128 nodes), meeting the needs of most enterprise and publicly-facing Web applications. Call it a micro-cloud computing development framework if you will. Using C++ for performance or Lua for rapid development, Web Wispers™ makes it easy to program popular applications such as Wikis, Web forums, blogs, and Web-based instant messaging while building in fault-tolerance and scaling capabilities from the get-go.

Ssrc Web Wispers™ simplifies programming by encouraging the use of single-threaded I/O event-driven processes. Although it is possible to write multi-threaded services with Ssrc Web Wispers, you will produce more robust and flexible applications by using the process as a unit of parallelism instead of the thread. Processes can be distributed across multiple nodes in a cluster or wide-area network, whereas threads cannot. If your workload and/or data exceeds the capacity of a single process, you can partition the workload and/or data between multiple processes.

For more information, read the overview.

We've discontinued making public releases of Wispers for the time being. The current in-house version is far ahead of the last public release, but caters rather narrowly to our specific development needs. We do not see it having wide appeal, especially without a voluminous quantity of explanatory and tutorial documentation we simply do not have the resources to produce. In the future, we may factor out some of the components into separately released open source libraries with a GitHub source repository mirror.

A Simple Example

The simplest form of Web application you can write with Web Wispers™ is a FastCGI program (either in C++ or Lua). Here is an example of a Lua FastCGI servlet that adds two numbers and produces an HTML page with the result.

local wispers = require('ssrc.wispers') function http_get(request_ptr, response_ptr) local request = wispers.fcgi_request(request_ptr) local param = wispers.parse_query_string(request:query_string()) local x, y, sum, msg if param.x and param.y then x, y = tonumber(param.x), tonumber(param.y) end if x and y then sum = x + y end if sum then msg = x .. " + " .. y .. " = " .. sum else local response = wispers.fcgi_response(response_ptr) msg = "Error: invalid arguments." response:set_status(wispers.StatusBadRequest) end return string.format("<html><head><title>%s</title></head><body><h1>%s</h1></body></html>", msg, msg) end

Clearly, there are ease of programming problems with FastCGI servlets. First, you must explicitly parse and validate all parameters. Second, you have to inline dynamic content (however, it is possible to include a template processing library such as ltp). FastCGI servlets are most appropriate for simple Web services that return a value instead of rendering pages dynamically.

In addition to programming complexity, FastCGI servlets suffer from the requirement that each servlet maintain a socket connection to the HTTP server front-end. Each new servlet requires a change to each HTTP server configuration associating a URL mount point with a servlet. Web Wispers™ Web services decouple the HTTP server interface, parameter parsing, and output rendering from request processing. One or more relays (either co-located with or remotely located from the HTTP servers) maintain FastCGI connections with the HTTP servers and asynchronously relay requests to the appropriate Web service based on the URL. Web service parameters are converted automatically to C++ or Lua data structures, although the programmer still retains the ability to access the raw parameters if required.

Should a request require a synchronous response, a Web service sends results to the relay, which forwards them to the client after rendering them via an output template (using ltp). The same Web service method can be re-used to generate a Web page, a SOAP message, or a JSON result by mapping different request actions to the Web service method and specifying different output templates for the results. Asynchronous results can be delivered via an event queue, eliminating the need for the client to maintain a persistent connection for long-lived transactions.

Here is an example of the addition service implemented as a Lua Web service module.

local ws_module = require('ssrc.wispers.ws_module') local function add(context, param) local x, y = tonumber(param.x), tonumber(param.y) local sum = x + y local template_data = context:response().template_data template_data:set_double(x, "x") template_data:set_double(y, "y") template_data:set_double(sum, "sum") end module_add = ws_module:new() module_add.ws_methods = { add = { one_way = false, requires_session = false, parameters = { x = { multi_value = false, optional = false, matches = [[\d+]], min_size = 1, max_size = 10 }, y = { multi_value = false, optional = false, matches = [[\d+]], min_size = 1, max_size = 10 } }, call = function(...) return add(module_add.context, ...) end } }

Although seemingly more complex than the first example, the Web service module is in fact simpler to write. The bulk of the code is a declarative description of the Web service method properties. Parameters are automatically validated for the programmer, allowing the add function to simply add the two numbers and populate the response. In a real application, the Web service module wouldn't be implemented to execute the business logic directly. Instead, it would forward parameters to a business object and convert its results into a response for the relay. Web Wispers™ is all about decoupling processing units from one another to maximize flexibility in combining them for optimal performance and ease of software maintenance.

Web services can be implemented as Lua modules, C++ dynamically loaded modules, or as stand-alone C++ services. Which one you choose will depend on your development goals. Furthermore, Web services often delegate data access to Wisp services. A common use case is to use a Web service as a domain-specific load-balancer that routes requests to the appropriate Wisp service based on data-partitioning, computational load-balancing, or availability criteria. How many HTTP servers, relays, Web services, and Wisp services you deploy will depend on your performance and fault-tolerance requirements and their relationship to your workload and data scaling characteristics. Web Wispers™ gives you the flexibility to distribute your resources optimally to meet your specific needs.

This product uses software developed by Spread Concepts LLC for use in the Spread toolkit. For more information about Spread, see http://www.spread.org/.