July 17, 2017 | Written by: Shyam Purkayastha
Categorized: How-tos | What's New
Share this post:
If you are a die-hard sports fan, then you probably get impatient too quickly. Particularly in a situation when you are unable to watch the match live. To add to the misery, the live score that you see on your phone is often playing a catch-up game. Sound like a familiar situation?
In this blog post, we present to you a model system for managing sports score streaming using the components of the IBM Bluemix platform, including PubNub. This system can serve live score updates in real-time to millions of users simultaneously. And, in case you want to indulge in betting, then it can do more to help swing the odds in your favor.
The Holy Grail of Sports Score Streaming
The real challenge of building such an app, for real-time streaming of scores, is not about streaming the live score itself. It’s all about the fascinating nuggets of information, that pertain to the statistics about the current game, the teams, and the players.
A live score just represents a minuscule piece of information that contains the current score of the match. If we take the example of basketball, then you would have surely spotted a giant scoreboard along side the basketball court, that looks somewhat like the image below.
This is the current live score of an ongoing basketball game, but the statistical information contains more data. This data can vary based on the subject (game, team, player) and context (home vs. away, opponents, season). Moreover, we need enormous historical data to calculate this.
The serverless way to build a live scoreboard
A sports streaming app is essentially a data streaming app that streams the score updates. In recent times, there has been a paradigm shift in building the server-side components for such data streaming apps. Instead of relying on heavy and dedicated cloud infrastructures, we see a shift towards lightweight and on-the-fly server components.
This approach means that we deploy the apps based on the “service logic” to be executed on the cloud and forget about the actual servers. This simplifies the business logic of a complex application by chaining it as a series of small, independent modules executing as microservices.
These microservices reside somewhere in the cloud. As a developer or deployment engineer, we do not care about their server IP address, login credentials, etc. All we need to do is create the microservice instances and hook up the data streams through them. It just works.
This is exactly the approach that we propose for this use case (see below).
Since we are dealing with live score data, as well as stats data, we can think of two separate microservice instances executing somewhere in the cloud. And as you can see, the stats generation and streaming is a little heavy operation. So we can optimize the logic by having a caching database layer that can be attached to the microservice.
Let’s look at two of the popular serverless platforms available under IBM Bluemix that we can use to build our live score streaming app.
Introducing IBM Openwhisk
IBM Openwhisk is a serverless computing platform. It is a distributed compute service that can execute application logic in response to events. It allows developers to compose their application’s business logic by defining a set of actions and invoking them via a set of triggers.
You can check out the OpenWhisk resource page for documentation and demo code samples.
PubNub Functions is a serverless computing platform that is optimized for building and scaling real-time applications. A Function represents a single microservice instance that executes a service logic on the PubNub Data Stream Network. It can also interact with third party cloud APIs, some of which are already prepackaged and available under the BLOCKS catalog.
PubNub Functions run as independent microservices within the PubNub’s data stream network but can invoke external services through REST APIs.
Let’s take a live basketball game. We have two teams: Toronto Raptors and Cleveland Cavaliers. Here is a sample run of the game simulation on a terminal console. Note that the game timer is fast forwarded such that one second represents one minute of gameplay.
You can see that in the top half of the console, the score gets updated along with the field goals scored by each team. This represents the live score data.
Apart from that, you can occasionally see the team stats in the bottom half of the console. This is a result of user interaction. The console accepts commands to display these metrics for each team. This represents the stats data.
As we emphasized before, the live stream and stats stream constitutes the two data streams that are consumed by the users of this app. Let’s have a deep dive at how to build the server backend of this app using the serverless paradigm.
Building the server side of live score streaming service
PubNub Functions is the heartland for executing any real-time data processing task. By default, the main function of this application is real-time streaming of live score. Hence we can straightaway use a Function instance to process the live stream. All this happens over the PubNub data stream network.
For stats streaming, we can use a separate Function which is attached to an OpenWhisk instance. The idea here is to process the stream through the Function while chaining it with the heavyweight stats computation and handled by an OpenWhisk action. The data required for this computation is stored in an IBM Cloudant instance.
Therefore, we end up with two Function instances for processing the live score stream and the stats stream, both sharing an OpenWhisk + Cloudant instance for assisting in stats computation.
IBM Cloudant is a NoSQL database and is also available under the IBM Bluemix catalog of services.
You can check out the entire source code of this demo app under this GitHub repository.
Here are the components of the source.
- Gamesimulation: The python script to simulate a basketball game play. It simulates a basketball game of 48 minutes by ticking the timer one second at a time, that represents one minute of game play. The scores are incremented and allotted to the teams in a random order during each tick.
- UI: A python script that represents the scoreboard UI console. This represents the end user application screen that receives the live scores and it also supports user interactivity to display team stats.
You can refer to the main README file to follow the configuration steps for launching the Openwhisk, Cloudant and PubNub Functions.
Once all the services are configured and running, you can run the game simulation script on your local computer and watch the live scores and stats.
(Note: For this setup, we have not provided any source code to run on the first Function for handling live score streaming. It uses the default Function code to handle the live stream.)
For building this app, you will need to create a Bluemix and PubNub account. Visit the IBM Bluemix signup page and PubNub service page to create your respective accounts. Both of the services offer a free tier account to play around with their offerings.
The innards of live score streaming service
Let’s take a look at how are we processing the data streams via this microservices network.
With PubNub, managing live score stream is a no-brainer. All we need is for the devices be hooked to the PubNub data stream via a PubNub channel. Once the scoreboard equipment, capturing the live score at the venue, is hooked to this channel, then all devices will start receiving the scores.
As there is no data transformation involved in the live score streaming, this also can be done without using a Function. But considering a real-world deployment, we have provided a Function that might be used for offering some additional options to the users.
For the stats data, users have to request it. In the current demo app, users can only choose to see the stats for the team. On receiving the request, the second Function will trigger an action from OpenWhisk, get the calculated stats data, and stream it back to the user.
Request for stats is sent on the channel, ‘Gameplaystats’ and the response data format is:
Once the ongoing live game is over, the first Function that handles the live score updates the Cloudant database to update the result of the game for each team (Currently this is done directly by the gamesimulation script).
The Cloudant database stores the match outcome for every team in the format shown below:
'Loss': <binary represents loss>,
'Win': <binary represents win>,
'Game': <default 1>,
'Team': <team name>,
'Totalscore': <total score of the team>,
'Minutesplayed': <duration of the game>
'_id': '2017-05-0320: 18: 51.905222',
In this way, after each match, the database gets updated with two records. This builds up the historical match database which is used for generating team stats in future.
I encourage you to extend this app to make it more realistic. Perhaps we can offer a live feed that contains scores from multiple live games happening simultaneously. That way, users can select which game they want to track. PubNub Functions can entirely handle this.
This is an ideal example of how two serverless architectures can co-exist and offer complementary values. In this case, Functions handles all real-time traffic. And for non real-time, time intensive operation, it can create a data flow where the operation on the data can be transformed along the way by chaining it with OpenWhisk. This would create a harmonious data stream that meets the end user’s expectation.
You can also try the the IBM OpenWhisk: Function-as-a-Service from the PubNub BLOCKS catalog, that has all the built-in code to invoke OpenWhisk from within a Function.
Questions? Comments? Feel free to post them to this blog article.