presentation – Live Video Platform for FIFA World Cup


In this talk, we will describe globo.com’s live video stream architecture, which was used to broadcast events such as the FIFA World Cup (with peak of 500K concurrent users), Brazilian election debates (27 simultaneous streams) and BBB (10 cameras streaming 24/7 for 3 months) .

NGINX is one of the main components of our platform, as we use it for content distribution, caching, authentication, and dynamic content. Besides our architecture, we will also discuss the Nginx and Operational System tuning that was required for a 19Gbps throughput in each node, the open source Cassandra driver for Nginx that we developed, and our recent efforts to migrate to nginx-rtmp.

Advertisements

presentation QCon 2015 – ptBR

http://www.infoq.com/br/presentations/contos-de-escalabilidade-na-plataforma-de-videos-online-da-globo

qcon-rio-2015-escalabilidade-na-plataforma-de-vdeos-ao-vivo-29-1024

In this presentation you’ll see how we developed (what we used) the live video platform for the FIFA World Cup 2014. It shows how we made it scalable using lots of open source solutions.

Keywords: linux, cassandra, nginx, redis, BGP, logstash, graphite, python, ruby, lua

Will we only create and use dynamic languages in the future?

Since I’ve playing with some dynamic languages (Ruby and Clojure), I have been thinking about why would anybody create a new static typed language?! And I didn’t get the answer.

I started programming in Visual Basic and I taste its roots, which are almost all full of procedure commands (bunch of do, goto and end), then I moved to C#, sharper it changes the end’s for }’s and give us a little more power based on some premises: we can treat two different things in the same way, polymorphism. The last static language, but not the least, I used (and I use it) Java, abusing of his new way of treating a set of things equality, the interfaces and using its “powers” on reflections.

Although when I started to use Ruby I saw that I could treat a group of things equality without doing any extra work. I still need to code models and composed types, even though we can create or change them dynamically using “real power” of metaprogramming.

When I start to study and apply the Clojure and its principles, my first reaction was the rejection, how can I go on without my formal objects, how can I design software without a model in the head and so on. I wasn’t thinking about how actually I do software, currently I use TDD to design software and I don’t think what models I need to have, I do think in terms of “what I want”. At minimum, Clojure make me think about, do we really need object to design software?! .  A three days ago I saw an amazing video about similar thoughts: Some thoughts on Ruby after 18 months of Clojure.

Summarising: With my limited knowledge of theses languages, let’s suppose we use a function (which we don’t have source code) and we want to do something before that function is executed (intercept) using: VB I’ll need to check every single piece of code which we call this function and call another one, in Java we can use a AOP framework, in Ruby we can use the spells of metaprogramming. It seems that some frameworks, patterns and extra work aren’t needed more because of this dynamic language evolution.

My conclusions using dynamic languages (Clojure/Ruby) for now it’s: I write less code and reuse them more easy, so I don’t see any reason to create/use a new static typed language, would you see any motivation to do that?

PS: When I use C# (.Net Framework 1.3 – 2.0) it was not so super cool as today.

Functional programming with Clojure

Clojure

I’ve been studying the new language called Clojure (all the cool kids are talking about Clojure). It is a functional language created by Rich Hickey around 2007. This is a(nother) dialect of Lisp. It is a dynamic language as Ruby, JavaScript and others. As said before Clojure (pronounced as closure) it’s a impure functional language in contrast with Haskell, a pure functional language. It runs over the JVM, so it’s fast, interoperable with Java among a lots of good stuffs that JVM give us. To put hands-on and try code something you can use the try Clojure online or you can download the clojure.jar file and run it. Surprisingly Clojure it’s easy to learn.


java -jar clojure-x.x.x.jar

What it a functional language? (concepts)

first-order functions -> functions are treated as values. You can store a function on a variable, you can pass one function to another or you can return a function from another function.

var sum = function(a,b){
  return a + b;
};

var obj = function(sum){
  return {
    hello: "hello",
    sum: sum
  };
}();

obj.sum(3,5);

functions constructs -> the language constructs are function instead of keyword. Constructions for conditions (if), for iterations (for, while), catch exceptions (try, catch) and others.


(if condition do-it else-do-it)

stateless -> it’s functional in the sense of math, you have functions which defines values input and output and doesn’t rely on outside global state. In such pure function you won’t produce any side-effect (read, write outside resource). Obviously we will produce programs which causes side-effects, clojure helps you build “mutable” data . On other pure languages like Haskell side-effects are treated as expections so you have concepts like actors and monad.

immutable data -> collections and local variable, in clojure, are immutable. The immutability, helps us in parallelism, since the “values” are immutable you can shared then without worry about locks.

currying -> is the technique of transforming a function that takes multiple arguments (or an n-tuple of arguments) in such a way that it can be called as a chain of functions each with a single argument (partial application).

memoization -> is an optimization technique used primarily to speed up computer programs by having function calls avoid repeating the calculation of results for previously processed inputs.

Resources

RSpec and Watir to test web applications

Testing is cool

Software testing

Software testing is an investigation conducted to provide stakeholders with information about the quality of the product or service under test. Software testing can also provide an objective, independent view of the software to allow the business to appreciate and understand the risks of software implementation. Test techniques include, but are not limited to, the process of executing a program or application with the intent of finding software bugs (errors or other defects) – Wikipedia

The main intend of this post is, introduce you to UI tests over some ruby toys. In fact you could create an entire project (new) in ruby just to test your legacy web project. It’s cool, you can learn new language and work for the improvement of your legacy product. If you are totally new for ruby maybe a ruby overview can help you. (or might confuse you more)

Installing ruby, watir and rspec

Instead of installing the ruby directly, we are going to install the RVM (Ruby Version Manager) to then install any ruby we need. The steps described here were made on Ubuntu 11.04. On your terminal do the magic to install RVM.

bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
echo ‘[[ -s “$HOME/.rvm/scripts/rvm” ]] && . “$HOME/.rvm/scripts/rvm” # Load RVM function’ >> ~/.bash_profile
source .bash_profile

And from now on, your life will be better on ruby interpreters versions. Let’s install the ruby 1.9.2. (terminal again)

rvm install 1.9.2

And if we want to see the rubies installed on our machine?

rvm list

And now, how can we chose one ruby to work on the terminal session?

rvm use 1.9.2

For the test purpose we will use Watir and RSpec, great tools for testing, make fun with BDD and the best thing is install them it’s very easy.

gem install watir-webdriver
gem install rspec

Hands-on

Since we have all things installed, we can move for the example. The feature I want to test is the search system of  Amazon. Being more precise, I want to search for ‘Brazil’ and see if the ‘Brazil on the Rise’ is within the results as I want to be sure when I search for ‘semnocao‘ the Amazon doesn’t provide any result. Now, we can write the spec.

require 'amazon_page'

describe AmazonPage do
 before(:each) do
   @page = AmazonPage.new
 end
 after(:each) do
   @page.close
 end
 it "should show 'Brazil on the Rise' when I query for [Brazil]" do
  @page.query 'Brazil'
  @page.has_text('Brazil on the Rise').should == true
 end
 it "should bring no result when I search for [semnocao]" do
  @page.query 'semnocao'
  @page.results_count.should == 0
 end
end

The specification is very simple, it will create a page before each test calling and close the page after each test calling. There is only two tests: test when you search for Brazil  and  when you search for semnocao. We will design the tests using page object pattern. The class bellow is the page which represents the Amazon page and all testable behaviors should be inside of it.

require 'watir-webdriver'

class AmazonPage
 def initialize
  @page = Watir::Browser::new :firefox
  @page.goto 'http://www.amazon.com'
 end
 def close
  @page.quit
 end
 def query(parameter)
  @page.text_field(:id=>'twotabsearchtextbox').set parameter
  @page.send_keys :enter
 end
 def has_text(text)
  @page.text.include? text
 end
 def results_count
    if @page.text.include? 'did not match'
     0
    else
     @page.div(:id=>'resultCount').text.split(' ')[5].gsub(',','').to_i
    end
 end
end

To run this you just need to type on your terminal.

rspec spec/

The final code can be downloaded or viewed at github.

Additions

  • We could improve our story readibility  with Cucumber.
  • We could send the browser execution to an Xvfb server. (A.K.A. running headless) The browser pops up really bothers me.
  • We could integrate it with our CI.
  • We could design a base Page class for provide common operations as mixin or something

ps: the post was very inspired by KK post and Saush.

Ruby overview

Introduction

Take a look at this, there is two classes: a person and a teacher. The person (originally) just know how to speak English and then teacher teach him speak other language, it can show you how powerful and beautiful ruby is.

class Person
 attr_accessor :name
 def speak_english
  puts "Hi people!"
 end
end

class BrPortugueseTeacher
 def teach(person)
  def person.speak_portuguese
   puts "Ola pessoal!"
  end
 end
end

bill_gates = Person.new
bill_gates.nome = "Bill Gates"
pasquale = Teacher.new
pasquale.teach bill_gates
#now bill gates knows portuguese
bill_gates.speak_portuguese

The intent here is just show a quick overview of ruby from a newbie.

Code’s comment

#one line comment
=begin
Multiply lines comment.
Given that ...
=end

String

String in ruby is mutable (but when you use the operator method + it creates another string, so to concatenate strings you should use the operator <<) and just a little tip avoid the concatenation by using + instead prefer use interpolation, a way to handle string very similar to expression language, and it’s faster than normal concatenation.

ran = 34434
who = "Leandro Moreira"
puts "#{who} generates this #{ran} number"

Conventions

Yet on mutability, when you write a method that can affect the internal state, you should use the bang operator (!) on method’s name.

old_source_name = "angeline"
puts old_source_name.capitalize
puts old_source_name.capitalize!

Another cool convention to Boolean methods is end them with ?

if account.cancelled?
 puts "Run Forest, run!"
end

Range object

In ruby you can use a type Range to describe ranges and its use is very easy.

zero_to_ten = (0..10) #inclusive
one_to_seven = (0...8) #exclusive
alphabetic = ('a'..'z') #you also can omit the (

It’s all object and quick tips

– Hey, language prints I win three times.

puts "I win " * 3

You can use anything on if statement and it can ben true or false (and nil which is false too).

A weird thing is one way of handle the regular expressions.

/myexp/ =~ "sentence"
#"sentence" matches myexp?

Another weird operator is or equals.

list ||= flights
#the list will just receive the flights if list is nil.

The classes are really open

One of the main features of ruby is Open Class, this is cool, you just can grab a class and write a new feature for it.

class String
 def do_nothing
  puts "doing nothig"
 end
end

And then you just call it.

"number".do_nothing

Let’s trick the addition operations on number.

class Fixnum
 def +(other)
  self - other
 end
end
puts 2+1
#and it will prints 1. (~:

Variable arguments

Sometimes you need to use this kind of flexibility.

user.buy computer
user.buy computer, mouse, monitor

To achieve this you just use the syntax. The splat operator how it is known.

def buy(*products)
 #buy logic
end

Hash enhancements

There is a lot of people which claims to use hash as parameter.

e_account.transfer :to_account => my, :value => 4800

def transfer (parameters)
 dest_account = parameters[:to_account]
 #...
end

Declarations

class Anything
 @field #object field
 @@field #class field
end

Singleton in Ruby

Singleton pattern is a design pattern used to implement the mathematical concept of a singleton, by restricting the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects (say, five). Some consider it an anti-pattern, judging that it is overused, introduces unnecessary limitations in situations where a sole instance of a class is not actually required, and introduces global state into an application.  (From wikipedia)

class HyperDao
@@instance = HyperDao.new
def self.instance
return @@instance
end
private_class_method :new
end

But we’re talking about ruby, don’t we?

require 'singleton'
class God
include Singleton
end

It’s done! 😀

Equals

If you want or need to rewrite the equals…

def ==(other)
 self.id = other.id
end

Duck typing – good-bye interface

Duck typing is a style of dynamic typing in which an object’s current set of methods and properties determines the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface. The name of the concept refers to the duck test, attributed to James Whitcomb Riley (see History below), which may be phrased as follows:”When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.” (From Wikipedia)

class PremiumAccount
 def saldo
   #
 end
end

class CommonAccount
 def saldo
  #
 end
end

The bank manager will accept that.

class BankManager
 def total_debt(accounts)
  for account in accounts do
   debt += account.saldo
  end
 end
end

Mixin

Mixin is a class that provides a certain functionality to be inherited or just reused by a subclass, while not meant for instantiation (the generation of objects of that class). Inheriting from a mixin is not a form of specialization but is rather a means of collecting functionality. A class may inherit most or all of its functionality from one or more mixins through multiple inheritance. (Again, from Wikipedia)

module Logging
 def log(message)
  puts message
 end
end

class Anything
 include Logging
  #...
end

any = Anything.new
any.log "It started now!"

Metaprogramming

Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data, or that do part of the work at compile time that would otherwise be done at runtime. In many cases, this allows programmers to get more done in the same amount of time as they would take to write all the code manually, or it gives programs greater flexibility to efficiently handle new situations without recompilation.

class Person
 attr_accessor :name
 def speak_english
  puts "Hi people!"
 end
end

class BrPortugueseTeacher
 def teach(person)
  def person.speak_portuguese
   puts "Ola pessoal!"
  end
 end
end

bill_gates = Person.new
bill_gates.nome = "Bill Gates"
pasquale = Teacher.new
pasquale.teach bill_gates
#now bill gates knows portuguese
bill_gates.speak_portuguese

Highly influenced by ruby on rails from Caelum.

Acceptance testing on Fitnesse using slim test system

What is Fitnesse?

  • It’s a software development collaboration tool.
  • It’s a software testing tool.
  • It’s a wiki.
  • It’s a web server.

This tool provides a way for the BA’s and/or customers write their acceptance testing on wikis and better than this, they can run theirs tests and see if it fails or pass right on the page. Install Fitnesse it’s very simple, you just download and execute. The fitnesse architecture provides two types of test system: slim and the well-known fit. For this tutorial I’ll use the slim.

The hands-on

Scenario: Given that I have the input1 and input2 Then the output Should Be input1 plus space input2. So let’s express the acceptance testing of this feature (or behavior if you want). In Fitnesse we can express this using the decision table, others examples of places to write tests are query table, script table, library table and etc.

|it should print guaqmire|
|input1|input2|output?|
|you|are|you are|
|family|guy|family guy|
|tests|enough|tests enough|

Explaining the table, the first line is the name of the fixture, the second line contains the inputs and outputs names and from the third line on it’s filled with testing data. The output table should look like this:
Let’s setup the wiki-page to it became runnable, edit the page and put these parameters on the page.

!define TEST_SYSTEM {slim}
!define TEST_RUNNER {C:\fit\slim\rubyslim\lib\run_ruby_slim.rb}
!define PATH_SEPARATOR { -I }
!define COMMAND_PATTERN {ruby -I %p %m}
!path C:\fit\slim\rubyslim\lib\
!path C:\fit\ruby\prj\

The first line is setting TEST_SYSTEM to configure fitnesse to use the slim protocol instead of default fit. As we will use slim and ruby, we’ll use the rubyslim library. The second line is setting the TEST_RUNNER to use the ruby slim. Third line defines the PATH_SEPARATOR, used by the COMMAND_PATTERN to separate paths. The fourth line is configuring the COMMAND_PATTERN that will execute the test itself, the two parameters %p (receives all the paths from the page and its ancestors) and %m (the fixture itself) are used to correctly perform the test. The lines with path just informs to fitnesse where it can found the libraries and the runtime files.

And now you can run, is it fails? Good, now let’s programming it in ruby, if you are a newbie ruby as me, your code might be something like this.

module Fixtures
  class ItShouldPrintGuaqmire
   def set_input1 input1
    @input1 = input1
   end
   def set_input2 input2
    @input2 = input2
   end
   def output
    "#{@input1} #{@input2}"
   end
  end
end

Ohh it continues to fail, shame on me. As you can see at the code, I put the fixture inside a module called Fixture, so we need to inform the fitness what module/package is my fixture and we can do that by a table.

|Import|
|Fixtures|

This special table only  configures where is the fixtures. Now let’s see the entire code for fitnesse wiki.

!define TEST_SYSTEM {slim}
!define TEST_RUNNER {C:\fit\slim\rubyslim\lib\run_ruby_slim.rb}
!define PATH_SEPARATOR { -I }
!define COMMAND_PATTERN {ruby -I %p %m}
!path C:\fit\slim\rubyslim\lib\
!path C:\fit\ruby\prj\

|Import|
|Fixtures|

|it should print guaqmire|
|input1|input2|output?|
|you|are|you are|
|family|guy|family guy|
|tests|enough|tests enough|

Running the tests should show

Bonus round – Fitnesse using slim protocol in Java

In fact to make it runnable in Java it’s easier, you don’t need any TEST_RUNNER or COMMAND_PATTERN in your wiki page, since Java it’s default for fitnesse and your final wiki should look like this:

!define TEST_SYSTEM {slim}
!path C:\fit\java\prj\fit-slim-java.jar

|Import|
|br.com.leandromoreira.fixtures|

|it should print guaqmire|
|input1|input2|output?|
|you|are|you are|
|family|guy|family guy|
|tests|enough|tests enough|

And your Java code can be something like this:

package br.com.leandromoreira.fixtures;

public class ItShouldPrintGuaqmire{
  private String input1;
  private String input2;
  public void setInput1(final String i1){
   input1 = i1;
  }
  public void setInput2(final String i2){
   input2 = i2;
  }
  public String output(){
   return input1 + " " + input2;
  }
}

Real world

Usually the real world projects requires a lots of libraries on path, setup pages and more than just decision table to write tests. For instance, you can see that use fitnesse with slim seems more portable , less coupled with runtime and easier to implement too. In the real world you also create wiki for the project and suite test page for stories and organize all your imports and configs on project level, when you are composing a wiki on fitnesse you can take advantage of the fact that all the pages extend the configs from theirs ancestors, so you can have a better project wiki and managable test suite pages.

Update – Issues with Ruby 1.9.x

If you are trying to use the ruby 1.9.x you will have some issues the first one is: require ‘jcode’ issue, I tried to solve it but then it started to show another error list_deserializer.rb:1:in `<‘: comparison of String with Float failed (ArgumentError)’.  Since I’m not (still) a ruby guy I don’t know how to fix it.