Ping-pong is an interesting game. It is a game where two players hit a lightweight ball back and forth across a table using small rackets. The game takes place on a hard table divided by a net. When you look at the game as an observer you see some interesting things. The players act only when the ball is on their side of the table. Only then a player swings the racket and the ball starts to travel the other way. When you are working in IT, you start to recognize other things as well. There is an asynchronous process in the game. The players react on ball and act on it. Also, the ball has travels from left to right, and from right to left. Another interesting thing is that players only swing when the ball can be hit, but in between the players don’t do anything else. Lets try to model this process in a serverless way.
The ping pong model
To model the game Serverless, we can use AWS Lambda as act as players. For the ball, we can take a message. For the playing table we can take two message queue, one for the ‘left-to-right’ motion and one for the ‘right-to-left’ motion and AWS SNS is a perfect fit. For the rackets we can use the act of ‘publishing a message’. We also have to have a way to start the game, which will be by ‘serving the ball’. AWS CloudWatch events is perfect for this job. It will send a message to the lambda to ‘start serving’. Of course, you only serve one time, so we have to deal with that. To define the logic simple Python scripts suffice combined with the Python SDK for Python. The game will be deployed by means of Sceptre to AWS defining the desired state configuration of the serverless infrastructure using AWS CloudFormation templates. I think this can actually work!
For the players we take two Lambdas that execute simple Python scripts. One Lambda is called ‘ping’ that starts the game, and the other one is called ‘pong’ that reacts by ‘hitting’ the ball back.
# remember the serve started = False def handler(event, ctx) -> None: global started if event.get('detail-type'): # cloudwatch event if not started: started = True # hit the ball publish(ctx.invoked_function_arn, 'ping-topic', 'ping') else: # other event # hit the ball publish(ctx.invoked_function_arn, 'ping-topic', 'ping')
def handler(event, ctx): # hit the ball publish(ctx.invoked_function_arn, 'pong-topic', 'pong')
The playing table
We can model the table by using two Amazon SNS queues that will receive the messages from one actor and route the stream of messages to the other actor. The queues must have permissions to invoke the lambdas.
PingTopic: Type: AWS::SNS::Topic Properties: TopicName: ping-topic Subscription: - Endpoint: !GetAtt PongFunction.Arn Protocol: lambda PongTopic: Type: AWS::SNS::Topic Properties: TopicName: pong-topic Subscription: - Endpoint: !GetAtt PingFunction.Arn Protocol: lambda InvokePingPermission: Type: AWS::Lambda::Permission Properties: FunctionName: !GetAtt PingFunction.Arn Action: lambda:invokeFunction Principal: sns.amazonaws.com SourceArn: !Ref PongTopic InvokePongPermission: Type: AWS::Lambda::Permission Properties: FunctionName: !GetAtt PongFunction.Arn Action: lambda:invokeFunction Principal: sns.amazonaws.com SourceArn: !Ref PingTopic
To actually start the game, a player must start serving. The Ping actor already has the logic setup for that. A CloudWatch event will trigger the Ping actor to start the game. CloudWatch must have permission to invoke the lambda.
CloudWatchEventsRule: Type: AWS::Events::Rule Properties: ScheduleExpression: rate(1 minute) State: ENABLED Targets: - Arn: !GetAtt PingFunction.Arn Id: scheduled-event InvokeLambdaPermission: Type: AWS::Lambda::Permission Properties: FunctionName: !GetAtt PingFunction.Arn Action: lambda:invokeFunction Principal: events.amazonaws.com SourceArn: !GetAtt CloudWatchEventsRule.Arn
The example project shows how to configure a project to create a serverless ping-pong game. The example can be deployed with
make deploy and removed with
A game like ping-pong is asynchronous by nature. Players play the game by reacting on events that are happening. Upon an event, players only have to do simple things like hitting the ball back. Serverless architectures are a perfect fit for asynchronous processes. By using message queues, asynchronous message passing and serverless compute, real life processes can be modeled in an event-driven way. Event Driven Architectures (EDA), like the ping-pong game we just created make efficient use of data centre resources and are the are a core architectural pattern and essential for serverless cloud computing. Next time we’ll look at how we can apply what we have learned from the ping-pong to and abstract some integration patterns from it!