Free Your Code - Backends in the Browser

, Alexander Goedde

WAMP allows to create Web applications composed of components with can talk to each other without restrictions. This e.g. allows to actively call into code running inside a browser from any other component.

Can console.log be spectacular?

More related posts:

Top

With server and infrastructure software, demonstrations of functionality are not often spectacular. Most of the time, all you get is console input and output. So when Tobias (project developer) calls me over to his workstation, enters a command in one console window, and some more or less cryptic letters appear in another one, I often struggle to share his enthusiasm for what just happened.

This was completely different when he showed me the following remote procedure call:

console output for calling a simple square function from one console, executed in the other

By itself, this is trivial. The fact that bowled me over was that the output on both sides was in browser consoles - in different browsers. Browser A had just made a remote procedure call to browser B!

Appropriately, one of the two browser tabs had the title "Backend". We were running what would traditionally be considered backend code in a browser.

My mind was duly blown. This felt big - and a complete violation of what I've come to understand as the separation of roles in a Web application!

What's going on?

So what's going on here? The above demo uses WAMP, an open application messaging protocol. The roles here are as follows:

A WAMP client making a call to a remote procedure, with a WAMP router routing this to a registered endpoint and returning the result to the caller.

It's a simple enough flow of data. This simplicity is mirrored in the code for making a callable procedure:


function square(x) {
   console.log("calculating square of ", x);
   return x * x;
}

session.register('com.math.square', square);

   

Before we dive deeper into what enables this distribution of roles, and what architectures it makes possible, let's first try to delve a little into the main present concept for Web application architecture. We'll cover some of the technical aspects that shaped this concept - and why this causes the above calls to feel so wrong.

The technical view: Clients and Servers

The classic distribution of roles in Web applications was determined by, and runs along called technical aspects.

There are clients and a server. Clients are Web browsers, with a lot of possibilities existing for the server (e.g. LAMP, node.js).

The roles of client and server are established by the nature of the HTTP connections: The client opens the connection and sends a request, the server then responds, and the connection is closed.

request/response diagram with a browser and server

Additionally, there are traditional assumptions regarding an asymmetry of capabilities of the two roles: the browser is resource constrained and a functionally very limited runtime, while the server has full capabilities and can draw on large resources.

As a consequence of the directionality of the connection and the asymmetry of capabilities, there is also a distribution of functionality based on these roles:

  • The browser is limited to what by necessity has to run in it, i.e. displaying the UI, and it needs to initiate interactions based primarily on user input.
  • The server provides all non-UI functionality, such as processing user input and storing data and has to wait for browser requests in order to send any data.

With browsers evolving at a rapid pace, more and more processing can in principle be done in JavaScript.

At the same time, the resource situation may in some cases be reversed from the classic picture, with a browser running on a quad-core i7 with oddles of RAM, served a shared hosting instance with restrained and inconstant resources.

In short: the asymmetry regarding functionality has shrunk radically, and the browser may well have more resources than the server.

Yet the changes to the roles have mostly been tentative. We still have browser frontends calling backends on the server.

This is mainly due to the fact that the asymmetry regarding connections, i.e. the request and response model, is more fundamental than the asymmetry in capabilities, and that it has been much more persistent.

WebSocket: Bi-directionality means equal peers

The stack of HTML5 technologies added a new protocol a few years ago which adds a new connection model and ends the asymmetry on connections: WebSocket.

WebSocket connections are established with an HTTP request from a client to a server. The request already contains an upgrade request to WebSocket.

Once established, the WebSocket connection is persistent and provides a bi-directional messaging channel between the browser and the server.

At the level of this connection, there is no meaningful technical distinction between client and server anymore. Both the browser and the server are equal peers, where each can request and push information as needed.

While the establishment of a WebSocket connection leverages the old roles in the request and response model, the connection itself is not restricted by these anymore.

The functional view: Clients and Routers

Equal peers make the technical distinction between client and server obsolete at the application level. Either peer of a connection may send messages at any time.

A meaningful distinction of roles here should be based on the functionality that each of the peers provides within the application.

In a distributed application, this is indicated by what types of messages a peer sends and is able to receive.

The functional roles here are no longer server and client, but sender and receiver - where any participant can be either.

For a simple one-to-one system, this would be all that is needed. Each of the two peers can (meaningfully) send any messages that the other has implemented a receiving endpoint for.

Two partners to a WebSocket connection, both calling each other.

This is obviously limiting: Real-world implementations consist of large numbers of peers, and the still existing, underlying technical distinction between clients and servers mean that not all peers can connect directly to each other.

To keep things working here, we need another functional role: a peer which mediates between other peers. This distributes calls and their results to relevant recipients. The third role is that of a router.

Senders and receivers are about the content and meaning of the messages and we can group peers who implement either or both functionality under 'clients'. They are distinct from 'routers', which are only concerned with a message's source and destination.

A functional view thus gets us peers which are 'clients' or 'routers'.

Three peers with a router routing calls between them.

(We'd welcome any suggestions for a better term than 'clients' - we haven't been able to come up with one.)

What this means

All of the above builds on top of the technical infrastructure of clients and servers. It adds a functional layer on top of this technical basis.

Within this functional layer, we are free to distribute functionality as best fits our use case.

We can transform a classic architecture such as this, where browser clients call different functionality on the server:

Two browsers call different functionality on a server.

We can move functionality off the server and into any other peer - and allow the server to call functionality as well.

Functionality distributed across browsers and server, with the server able to call functionality in the browser.

Quite often this will leave us with a both a technical infrastructure and distribution of functionality that is similar to what we have now. We'll still have clients in the technical sense which connect to a central server, and most of the functionality will be on that server.

What we'll have gained is the flexibility to distribute any parts that make sense off to other client or servers - and the channel from the server to the client.

Whether you want to do something like do distributed OCR, or request collected temperature and position data from clients only when there's a need for it - you have the possibility to do so.

Depending on the use case, the changes may go further and you may end up with radically different distributions which would not have been possible under the old client/server model.

To show how far this separation of technical and functional roles goes, here's a possible architecture:

Functionality distributed across browsers and server, with the server able to call functionality in the browser.

Here a browser client connects to several servers. Once the connections are established, it is a peer like any other - and could play the role of router for server calls to each other.

I honestly can't see anybody ever actually implementing the above infrastructure - but it is exciting and liberating to have a design space where something like this is possible.

WAMP - Clients, Routers, PubSub and RPCs

The above is the high-level picture - the functional layer we want to enable.

WAMP (Web Application Messaging Protocol), a protocol we at Tavendo have designed, is our way to get there.

WAMP, which is an open source protocol, provides two messaging patterns:

  • RPC (Remote Procedure Call) - Calling code at a remote endpoint and receiving the result. This is what we need for the above application architectures.
  • PubSub (Publish and Subscribe) - A client can send events for topics, and these are routed to any clients which have subscribed for this topic with the router.

These two patterns cover the essentials for distributed Web applications with potentially huge numbers of peers.

Any device can, in principle, contain any combination or roles here, e.g. a router could additionally send and receive PubSub events, while a client both send and receive PubSub events, offer RPC endpoints and call remote procedures.

With WAMP, you can freely distribute you functionality across servers and browsers. (You can't, however, run a router in the browser. Enabling this hasn't exactly been high up on our list of priorities.)

(If you're interested, you can read a more detailed explanation of the thinking behing the design of WAMP)

Beyond the Browser

So far, we have talked about Web applications, i.e. browsers and servers.

Our JavaScript implementation of WAMP (Autobahn|JS) runs both in the browser and on node.js - so that's one modern server technology already covered.

Additionally, we have libraries for Python and C++, with an Android library and a connector to PL/SQL code in PostgreSQL in the works.

There are also third party implementations for JavaScript and Lua, and an Erlang implementation has just been started. We expect more implementations to come.

This means that you already have quite a bit of choice regarding technology for implementing a WAMP application.

Your application architecture can include browsers, native mobile applications, native desktop applications, embedded devices and classic servers.

While WAMP is an open protocol, and there are third-party routers, I'd recommend you take a look at Crossbar.io, our application router implementation.

Crossbar.io is open source, offers a full WAMP implementation, and a lot of other features to ease the development of distributed Web Applications, e.g. hosting and monitoring of application components.

Crossbario as the connector between browser, mobile, server, embedded and database clients.

A web of components - on the Web

The 'Web' in 'WAMP' stands for more than browsers and the WWW. It's about distributed application architectures - a web of functionality distributed across whatever devices make sense for your application.

In the near term, this fundamental change from a technical to a functional architecture will often be an evolution for application design. There is more design freedom, and a lot of things get much easier, but the underlying factors don't chane.

For Web applications there will usually still be backend code on the server, and a frontend in the browser. The frontends will be naturally more reactive, with the server able to push information to them, and they will contain more functionality when it makes sense to move it there.

In the long term, maybe someone will happen across a use case for a Web application where it makes sense to have all the functionality in browsers, and no classic server backend. I have no idea what this might be - but it's good to know that it is already covered.

Start experimenting and prototyping for IoT applications with Crossbar.io and Raspberry Pi!

Loaded with all the software you need to make the board part of WAMP applications!



Learn more

Recent posts

Atom Feed

Search this Site

Stay Informed

Sign up for our newsletter to stay informed of new product releases and features: