Distributed architecture

Object-based system

The simplest distributed system were composed of objects interacting with each other using Remote Precedure Calls(RPCs)

server.go
type Args struct {
A, B int
}
type MuliplyService struct{}
func (t *Arith) Do(args *Args, reply *int) error {
*reply = args.A * args.B
return nil
}
func main() {
service := new(MuliplyService)
rpc.Register(MuliplyService)
rpc.HandleHTTP()
l, err := net.Listen("tcp", ":1234")
if err != nil {
log.Fatal("listen error:", err)
}
go http.Serve(l, nil)
}
client.go
func main() {
client, err := rpc.DialHTTP(
"tcp",
serverAddress + ":1234"
)
if err != nil {
log.Fatal("dialing:", err)
}
// synchronous rpc
args := &server.Args{3,4}
var reply int
client.Call("Multiply.Do", args, &reply)
fmt.Printf(" %d*%d=%d", args.A, args.B, reply)
}

This style of architecture has lost popularity in recent years due to the following reasons:

  • It tries to add a wrapper for remote objects and fakes a local reference to a remote object, remote behavior is never the same as local.
  • The caller and collie both need to be up and running at the time of communication

Layered architectures

Components are organized into tiers and communication is restricted only between adjacent layers

For example, a typical web application design consists of the following

  • A Presentation layer: A UI-related functionality.
  • A Business Logic layer: Hosts the actual processing to be done as per the business rules.
  • A Data Layer: Deals with interactions with durable data (database)

Peer-2-peer (P2P) architecture

In the P2P architecture model, all the actors are peers and there is no central coordinator between them.

But the problem is with redistribution. One of the main requirements of distributed systems is scalability—the ability to add/remove servers to scale with load. If we change the number of ours servers, then the hash values will change.

Consistent hashing

Distributed computations

Google pioneered a new way of solving computations on multiple machines called MapReduce. The same code can work with different data on a set of commodity machines. MapReduce defines the processing in two parts:

  • Map: Take input and produces list of key value pairs.
  • Reduce: Aggregate these pairs and do computation.

Apache Spark: In memory, caching to improve computation speed.

Event driven architecture

The behaviour is composed by reacting to events.

  • The messaging bus serves as the event delivery mechanism
  • Services listen on Topics in the message queue, consume new messages, and then reacts to them.

Stream processing

On our travel website, we want to know the number of visitors in the last 30 minutes and get a notification when this number crosses a threshold (say, 100,000 visitors)

Apache Storm is an example of a stream processing framework.

There are also Complex Event Processing (CEP) engines, which allow users to write SQL like queries on a stream of events(Kafka). This pattern was developed initially for stock-market-related use cases.

The following diagram summarizes the different stream processing techniques

References

Book- Hands-On Software Architecture with Golang

Last updated on