SlideShare a Scribd company logo
Building
Distributed Systems
decision guide
Oleksiy Kurnenkov
Core Infrastructure
Domain lead
OnApp
Building
Distributed Systems
decision guide
Introduction
Part I
Distributed system
is a set of interconnected functional units with separate
runtime context
MONOLITH : DISTRIBUTED
1 Runtime context
Coroutines
Threads
Process
N Runtime contexts
Nodes
Components
Clusters
Grids
SCALE
Small ->
Middle ->
Global ->
OS, LAN
LAN
WAN
TYPES
CDN
Grids
Clouds
Clusters
Enterprise
CDN
Grid
Globus Toolkit 6
BOINC
x-Torrent
Cloud
Cluster
Enterprise
TASKS
MMOG
Analysis
Sensors
Real Time Enterprise
Media
Storage
Computation
Transactions
Challenges
Availability
Scalability
Security
Openness
Heterogeneity
Concurrency
Transparency
Feasibility
It IS there
99.9999999%
Availability
It grows and shrinks
Scalability
U ain’ gonna crack it
>:|
Security
It is open for development
and integration
Opennes
Everything changes
Heterogeneity
Parallel workloads
Concurrency
Less know - less depend
Transparency
Simplify as possible
Feasibility
Fallacies
The network is reliable
Latency is zero
Bandwidth is infinite
The network is secure
Topology doesn't change
There is one administrator
Transport cost is zero
The network is homogeneous
Mechanics
Part II
Mechanics
I
Membership
Concurrency / Parallelism
Synchronization
Coordination
Consensus
Clustering
Who’s there?
Membership
Membership
Heartbeats
Up-2-date list of nodes
We are Legion
Concurrency / Parallelism
Concurrency / Parallelism
Actors
Process Calculi
Shared memory
MY precious!
Synchronization
Synchronisation
Mutex | Semaphore
Distributed Lock
Roger that!
Coordination
Coordination
Leader election
Orchestration
the ‘Two Generals Problem’
Deal
Consensus
Consensus
Quorum
Consistency Availability Partition tolerance
Altogether
Clustering
Clustering
Load Balancing
Redundancy
Availability
Replication
Partition tolerance
Mechanics
II
Scaling
Fault Detection
Failover
Recover
Fail back
Scaling
Vertical
Horisontal
Automatic
Fault Detection
Monitoring
Supervision
Activity Analysis
Failover
Data | State Accessibility
Resource allocation
Spare Capacity
Business Continuity
Recovery
State Reconstruction
Data backup
State dump
Failback
Data consistency
Conflict resolution
Apache YARN
Apache Zookeeper
Apache Mesos
Apache Drill
Google Chubby
CoreOS
Google Kubernetes
Google Dremel
Architecture
Part III
Client - Server
N-tier
Service oriented Architecture
Event Driven Architecture
P2P
Context
Building Distributed Systems
System Allocation
Architectural
entities
decomposition
Subsystem
Service
Component
Process
Object
Middleware
Fractal
Building Distributed Systems
Subsystem -> Component -> Process -> Object
Subsystem -> Component -> Process -> Object
Subsystem -> Component -> Process -> Object
Communication
Infrastructure
aka Middleware
IPC
-----------------------------
Remote Invocation
Group Communication
Messaging
IPC
Share data
Send data
Remote Invocation
Request - Reply
RPC
RMI
Group Communication
{ Uni | Multi | Broad } cast
Publish | Subscribe
Messaging
Message Queue
Message Broker
Pipe | Filter | Translator
Implementation
Part IV
Microcosm ->
Macrocosm
Middleware
[ * ] Process
Host
Network
Within a process
Threads
Shared memory
Mutex | Monitor
require 'thread'
class RaceCondition
def initialize(resource, concurrency_level)
@resource = resource
@concurrency_level = concurrency_level
end
def perform
@concurrency_level.times do
threads << Thread.new { action }
end
threads.each(&:join)
end
private
def threads
@threads ||= []
end
def action
@resource += 1
puts @resource
end
end
RaceCondition.new(0, 10).perform
# 12
# 3
# 5
# 6
# 7
# 8
# 910
# 4
require 'thread'
class Sycnhronizer
def initialize(resource, concurrency_level)
@resource = resource
@concurrency_level = concurrency_level
end
def perform
@concurrency_level.times do
threads << Thread.new { action }
end
threads.each(&:join)
end
private
def threads
@threads ||= []
end
def action
lock.synchronize do
@resource += 1
puts @resource
end
end
def lock
@lock ||= Mutex.new
end
end
Sycnhronizer.new(0, 10).perform
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
# 10
Microcosm ->
Macrocosm
Process
[ * ] Host
NetworkMiddleware
Within a host
Processes
MQ | Shared memory | Pipes | UNIX Socket
Semaphore
# http://bogomips.org/ruby_posix_mq/
require 'posix_mq'
class Producer
attr_reader :mq
def initialize(mq_name)
@mq = POSIX_MQ.new("/foo", :rw)
end
def send(message, prio = 0)
puts "Send: #{message}. Priority #{prio}"
mq.send("#{message} #{prio}", prio)
end
end
p = Producer.new("/test_ipc")
p.send("Hello from #{Process.pid}", 10)
p.send("Hello from #{Process.pid}", 2)
p.send("Hello from #{Process.pid}", 0)
p.send("Hello from #{Process.pid}", 1)
p.send("Hello from #{Process.pid}", 20)
# ruby posix_mq/producer.rb
#
# Send: Hello from 12635. Priority 10
# Send: Hello from 12635. Priority 2
# Send: Hello from 12635. Priority 0
# Send: Hello from 12635. Priority 1
# Send: Hello from 12635. Priority 20
# http://bogomips.org/ruby_posix_mq/
require 'posix_mq'
class Consumer
attr_reader :mq
def initialize(mq_name)
@mq = POSIX_MQ.new("/foo", :rw)
end
def receive
mq.receive.first
end
def receive_non_block
mq.nonblock = true
begin
receive
rescue Errno::EAGAIN
mq.nonblock = false
puts "Nothing"
end
end
def shift
mq.tryshift
end
end
c = Consumer.new("/test_ipc")
while m = c.shift
puts "got: #{m}"
end
# ruby posix_mq/consumer.rb
# got: Hello from 12635 10
# got: Hello from 12635 20
# got: Hello from 12635 2
# got: Hello from 12635 1
# got: Hello from 12635 0
# https://github.com/pmahoney/process_shared
require 'process_shared'
mutex = ProcessShared::Mutex.new
mem = ProcessShared::SharedMemory.new(:int)
mem.put_int(0, 0)
pid1 = fork do
puts "in process 1 (#{Process.pid})"
10.times do
sleep 0.01
mutex.synchronize do
value = mem.get_int(0)
sleep 0.01
puts "process 1 (#{Process.pid}) incrementing"
mem.put_int(0, value + 1)
end
end
end
pid2 = fork do
puts "in process 2 (#{Process.pid})"
10.times do
sleep 0.01
mutex.synchronize do
value = mem.get_int(0)
sleep 0.01
puts "process 2 (#{Process.pid}) decrementing"
mem.put_int(0, value - 1)
end
end
end
Process.wait(pid1)
Process.wait(pid2)
# ruby shm.rb
#
# in process 1 (8038)
# in process 2 (8041)
# process 1 (8038) incrementing
# process 2 (8041) decrementing
# process 1 (8038) incrementing
# process 2 (8041) decrementing
# process 1 (8038) incrementing
# process 2 (8041) decrementing
# process 1 (8038) incrementing
# process 2 (8041) decrementing
# process 1 (8038) incrementing
# process 2 (8041) decrementing
# process 1 (8038) incrementing
# process 2 (8041) decrementing
# process 1 (8038) incrementing
# process 2 (8041) decrementing
# process 1 (8038) incrementing
# process 2 (8041) decrementing
# process 1 (8038) incrementing
# process 2 (8041) decrementing
# process 1 (8038) incrementing
# process 2 (8041) decrementing
# value should be zero: 0
rd_child, wr_parent = IO.pipe
rd_parent, wr_child = IO.pipe
pid = fork do
rd_parent.close
wr_parent.close
wr_child.puts "sent from child process"
puts rd_child.gets
end
rd_child.close
wr_child.close
wr_parent.write "sent from parent process"
puts rd_parent.gets
# ruby pipes/pipes.rb
#
# sent from child process
# sent from parent process
require 'eventmachine'
module UnixServer
def receive_data(data)
puts data
EM.stop if data.chomp == "exit"
send_data("Server #{Process.pid}: Got #{data.chomp} from you")
close_connection_after_writing
end
end
EM.run do
puts "Started UNIX socket server on /tmp/sock"
EM::start_unix_domain_server("/tmp/sock", UnixServer)
end
# ruby server.rb
#
# Started UNIX socket server on /tmp/sock
#
# HELLO! My pid is 13847
require 'socket'
UNIXSocket.open("/tmp/sock") do |c|
c.write("HELLO! My pid is #{Process.pid}")
puts c.read
end
# ruby client.rb
#
# Server 13843: Got HELLO! My pid is 13847 from you
Microcosm ->
Macrocosm
Process
Host
[ * ] NetworkMiddleware
Over the Network
{ TCP | UDP } Socket
HTTP Client - Server
Async messaging
require "bunny"
conn = Bunny.new
conn.start
ch = conn.create_channel
q = ch.queue("hello")
puts " [*] Waiting for messages in #{q.name}. To exit press CTRL+C"
q.subscribe(:block => true) do |delivery_info, properties, body|
puts " [x] Received #{body}"
# cancel the consumer to exit
delivery_info.consumer.cancel
end
require "bunny"
conn = Bunny.new(:hostname => "rabbit.local")
conn.start
ch = conn.create_channel
q = ch.queue("hello")
ch.default_exchange.publish("Hello World!", :routing_key => q.name)
puts " [x] Sent 'Hello World!'"
conn.close
require "bunny"
conn = Bunny.new
conn.start
ch = conn.create_channel
x = ch.fanout("logs")
msg = ARGV.empty? ? "Hello World!" : ARGV.join(" ")
x.publish(msg)
puts " [x] Sent #{msg}"
conn.close
require "bunny"
conn = Bunny.new
conn.start
ch = conn.create_channel
x = ch.fanout("logs")
q = ch.queue("", :exclusive => true)
q.bind(x)
puts " [*] Waiting for logs. To exit press CTRL+C"
begin
q.subscribe(:block => true) do |delivery_info, properties, body|
puts " [x] #{body}"
end
rescue Interrupt => _
ch.close
conn.close
end
Building Distributed Systems
Apache Kafka
RabbitMQ
Next time
To be continued:
Algorithms, patterns,
code!
Thank you!
Q&A

More Related Content

What's hot (20)

DOCX
SDN Training - Open daylight installation + example with mininet
SAMeh Zaghloul
 
PDF
cpu-affinity
Magnetic Poetry
 
PDF
Python twisted
Mahendra M
 
PDF
Run Run Trema Test
Hiroshi Ota
 
ODP
Testing Wi-Fi with OSS Tools
All Things Open
 
PDF
Rust: Reach Further
nikomatsakis
 
PPT
Interface between kernel and user space
Susant Sahani
 
PPTX
Coscup SDN workshop - mininet
HungWei Chiu
 
PPTX
Zookeeper Architecture
Prasad Wali
 
PPT
Laboratory exercise - Network security - Penetration testing
seastorm44
 
PDF
DDP - Meteor
Michael Lazarski
 
PPT
Backtracking Algorithmic Complexity Attacks Against a NIDS
amiable_indian
 
PDF
Hands-on ethernet driver
SUSE Labs Taipei
 
PPTX
Elephants and Mice
martin_casado
 
KEY
Non blocking io with netty
Zauber
 
PPTX
Open v switch20150410b
Richard Kuo
 
PDF
TCP Sockets Tutor maXbox starter26
Max Kleiner
 
PDF
FS2 mongo reactivestreams
yann_s
 
PDF
New Virtualization Technologies
Open Networking Perú (Opennetsoft)
 
PDF
LibreSSL, one year later
Giovanni Bechis
 
SDN Training - Open daylight installation + example with mininet
SAMeh Zaghloul
 
cpu-affinity
Magnetic Poetry
 
Python twisted
Mahendra M
 
Run Run Trema Test
Hiroshi Ota
 
Testing Wi-Fi with OSS Tools
All Things Open
 
Rust: Reach Further
nikomatsakis
 
Interface between kernel and user space
Susant Sahani
 
Coscup SDN workshop - mininet
HungWei Chiu
 
Zookeeper Architecture
Prasad Wali
 
Laboratory exercise - Network security - Penetration testing
seastorm44
 
DDP - Meteor
Michael Lazarski
 
Backtracking Algorithmic Complexity Attacks Against a NIDS
amiable_indian
 
Hands-on ethernet driver
SUSE Labs Taipei
 
Elephants and Mice
martin_casado
 
Non blocking io with netty
Zauber
 
Open v switch20150410b
Richard Kuo
 
TCP Sockets Tutor maXbox starter26
Max Kleiner
 
FS2 mongo reactivestreams
yann_s
 
New Virtualization Technologies
Open Networking Perú (Opennetsoft)
 
LibreSSL, one year later
Giovanni Bechis
 

Viewers also liked (7)

PDF
Building a team by Doina Leca
Pivorak MeetUp
 
PDF
Piotr Szotkowski about "Bits of ruby"
Pivorak MeetUp
 
PDF
Piotr Szotkowski about "Ruby smells"
Pivorak MeetUp
 
PDF
04 (IDNOG02) Cloud Infrastructure by Dondy Bappedyanto
Indonesia Network Operators Group
 
PDF
Handout1
milan_chbr
 
PPTX
Open Data in Indonesia - ODDC Research Update
Open Data Research Network
 
PDF
Lets build a game (in 24 min) by Ivan Zarea
Pivorak MeetUp
 
Building a team by Doina Leca
Pivorak MeetUp
 
Piotr Szotkowski about "Bits of ruby"
Pivorak MeetUp
 
Piotr Szotkowski about "Ruby smells"
Pivorak MeetUp
 
04 (IDNOG02) Cloud Infrastructure by Dondy Bappedyanto
Indonesia Network Operators Group
 
Handout1
milan_chbr
 
Open Data in Indonesia - ODDC Research Update
Open Data Research Network
 
Lets build a game (in 24 min) by Ivan Zarea
Pivorak MeetUp
 
Ad

Similar to Building Distributed Systems (20)

PDF
Lindsay distributed geventzmq
Robin Xiao
 
PDF
Scaling Ruby with Evented I/O - Ruby underground
Omer Gazit
 
PPTX
Linux Inter Process Communication
Abhishek Sagar
 
PPTX
3 processes
ari9_dutta
 
PDF
Redis: REmote DIctionary Server
Ezra Zygmuntowicz
 
KEY
Servers with Event Machine - David Troy - RailsConf 2011
David Troy
 
KEY
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
Eleanor McHugh
 
PDF
Lecture 3_Processes in Operating Systems.pdf
jamesLau66
 
PDF
ITFT_Inter process communication
Sneh Prabha
 
PDF
Distributed and concurrent programming with RabbitMQ and EventMachine Rails U...
Paolo Negri
 
PDF
sockets SMTP Bmsce ppt information science and engineering
UtkarshaMahajan6
 
PPTX
Network Programming-Python-13-8-2023.pptx
ssuser23035c
 
PDF
Concurrency: Rubies, Plural
Eleanor McHugh
 
PDF
Concurrency: Rubies, plural
ehuard
 
PPT
Advanced Operating System, Distributed Operating System
Shikha Manrai
 
PPT
Ch3
rupalidhir
 
PPT
Parallel systemhhzgzhzbzhhzhzhuzhzhzhhzhzh
zaid347427
 
PDF
Inter-Process Communication in distributed systems
Aya Mahmoud
 
PDF
DCS Unit-II COMMUNICATION AND COORDINATION.pdf
rameshwarchintamani
 
PDF
Ruby Microservices with RabbitMQ
Zoran Majstorovic
 
Lindsay distributed geventzmq
Robin Xiao
 
Scaling Ruby with Evented I/O - Ruby underground
Omer Gazit
 
Linux Inter Process Communication
Abhishek Sagar
 
3 processes
ari9_dutta
 
Redis: REmote DIctionary Server
Ezra Zygmuntowicz
 
Servers with Event Machine - David Troy - RailsConf 2011
David Troy
 
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
Eleanor McHugh
 
Lecture 3_Processes in Operating Systems.pdf
jamesLau66
 
ITFT_Inter process communication
Sneh Prabha
 
Distributed and concurrent programming with RabbitMQ and EventMachine Rails U...
Paolo Negri
 
sockets SMTP Bmsce ppt information science and engineering
UtkarshaMahajan6
 
Network Programming-Python-13-8-2023.pptx
ssuser23035c
 
Concurrency: Rubies, Plural
Eleanor McHugh
 
Concurrency: Rubies, plural
ehuard
 
Advanced Operating System, Distributed Operating System
Shikha Manrai
 
Parallel systemhhzgzhzbzhhzhzhuzhzhzhhzhzh
zaid347427
 
Inter-Process Communication in distributed systems
Aya Mahmoud
 
DCS Unit-II COMMUNICATION AND COORDINATION.pdf
rameshwarchintamani
 
Ruby Microservices with RabbitMQ
Zoran Majstorovic
 
Ad

More from Pivorak MeetUp (20)

PDF
Lisp(Lots of Irritating Superfluous Parentheses)
Pivorak MeetUp
 
PDF
Some strange stories about mocks.
Pivorak MeetUp
 
PDF
Business-friendly library for inter-service communication
Pivorak MeetUp
 
PDF
How i was a team leader once
Pivorak MeetUp
 
PDF
Rails MVC by Sergiy Koshovyi
Pivorak MeetUp
 
PDF
Introduction to Rails by Evgeniy Hinyuk
Pivorak MeetUp
 
PPTX
Ruby OOP (in Ukrainian)
Pivorak MeetUp
 
PDF
Testing in Ruby
Pivorak MeetUp
 
PDF
Ruby Summer Course by #pivorak & OnApp - OOP Basics in Ruby
Pivorak MeetUp
 
PDF
The Saga Pattern: 2 years later by Robert Pankowecki
Pivorak MeetUp
 
PDF
Data and Bounded Contexts by Volodymyr Byno
Pivorak MeetUp
 
PDF
Successful Remote Development by Alex Rozumii
Pivorak MeetUp
 
PDF
Origins of Elixir programming language
Pivorak MeetUp
 
PDF
Functional Immutable CSS
Pivorak MeetUp
 
PDF
Multi language FBP with Flowex by Anton Mishchuk
Pivorak MeetUp
 
PDF
Detective story of one clever user - Lightning Talk By Sergiy Kukunin
Pivorak MeetUp
 
PDF
CryptoParty: Introduction by Olexii Markovets
Pivorak MeetUp
 
PDF
How to make first million by 30 (or not, but tryin') - by Marek Piasecki
Pivorak MeetUp
 
PDF
GIS on Rails by Oleksandr Kychun
Pivorak MeetUp
 
PDF
Unikernels - Keep It Simple to the Bare Metal
Pivorak MeetUp
 
Lisp(Lots of Irritating Superfluous Parentheses)
Pivorak MeetUp
 
Some strange stories about mocks.
Pivorak MeetUp
 
Business-friendly library for inter-service communication
Pivorak MeetUp
 
How i was a team leader once
Pivorak MeetUp
 
Rails MVC by Sergiy Koshovyi
Pivorak MeetUp
 
Introduction to Rails by Evgeniy Hinyuk
Pivorak MeetUp
 
Ruby OOP (in Ukrainian)
Pivorak MeetUp
 
Testing in Ruby
Pivorak MeetUp
 
Ruby Summer Course by #pivorak & OnApp - OOP Basics in Ruby
Pivorak MeetUp
 
The Saga Pattern: 2 years later by Robert Pankowecki
Pivorak MeetUp
 
Data and Bounded Contexts by Volodymyr Byno
Pivorak MeetUp
 
Successful Remote Development by Alex Rozumii
Pivorak MeetUp
 
Origins of Elixir programming language
Pivorak MeetUp
 
Functional Immutable CSS
Pivorak MeetUp
 
Multi language FBP with Flowex by Anton Mishchuk
Pivorak MeetUp
 
Detective story of one clever user - Lightning Talk By Sergiy Kukunin
Pivorak MeetUp
 
CryptoParty: Introduction by Olexii Markovets
Pivorak MeetUp
 
How to make first million by 30 (or not, but tryin') - by Marek Piasecki
Pivorak MeetUp
 
GIS on Rails by Oleksandr Kychun
Pivorak MeetUp
 
Unikernels - Keep It Simple to the Bare Metal
Pivorak MeetUp
 

Recently uploaded (20)

PPTX
Agentic Automation Journey Series Day 2 – Prompt Engineering for UiPath Agents
klpathrudu
 
PPTX
Migrating Millions of Users with Debezium, Apache Kafka, and an Acyclic Synch...
MD Sayem Ahmed
 
PDF
4K Video Downloader Plus Pro Crack for MacOS New Download 2025
bashirkhan333g
 
PPTX
Transforming Mining & Engineering Operations with Odoo ERP | Streamline Proje...
SatishKumar2651
 
PDF
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
PDF
SciPy 2025 - Packaging a Scientific Python Project
Henry Schreiner
 
PDF
Linux Certificate of Completion - LabEx Certificate
VICTOR MAESTRE RAMIREZ
 
PDF
Thread In Android-Mastering Concurrency for Responsive Apps.pdf
Nabin Dhakal
 
PDF
Download Canva Pro 2025 PC Crack Full Latest Version
bashirkhan333g
 
PDF
유니티에서 Burst Compiler+ThreadedJobs+SIMD 적용사례
Seongdae Kim
 
PDF
AI + DevOps = Smart Automation with devseccops.ai.pdf
Devseccops.ai
 
PPTX
Homogeneity of Variance Test Options IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
PPTX
Hardware(Central Processing Unit ) CU and ALU
RizwanaKalsoom2
 
PDF
MiniTool Partition Wizard 12.8 Crack License Key LATEST
hashhshs786
 
PDF
MiniTool Partition Wizard Free Crack + Full Free Download 2025
bashirkhan333g
 
PDF
Alarm in Android-Scheduling Timed Tasks Using AlarmManager in Android.pdf
Nabin Dhakal
 
PPTX
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
PDF
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
PPTX
AEM User Group: India Chapter Kickoff Meeting
jennaf3
 
PDF
Wondershare PDFelement Pro Crack for MacOS New Version Latest 2025
bashirkhan333g
 
Agentic Automation Journey Series Day 2 – Prompt Engineering for UiPath Agents
klpathrudu
 
Migrating Millions of Users with Debezium, Apache Kafka, and an Acyclic Synch...
MD Sayem Ahmed
 
4K Video Downloader Plus Pro Crack for MacOS New Download 2025
bashirkhan333g
 
Transforming Mining & Engineering Operations with Odoo ERP | Streamline Proje...
SatishKumar2651
 
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
SciPy 2025 - Packaging a Scientific Python Project
Henry Schreiner
 
Linux Certificate of Completion - LabEx Certificate
VICTOR MAESTRE RAMIREZ
 
Thread In Android-Mastering Concurrency for Responsive Apps.pdf
Nabin Dhakal
 
Download Canva Pro 2025 PC Crack Full Latest Version
bashirkhan333g
 
유니티에서 Burst Compiler+ThreadedJobs+SIMD 적용사례
Seongdae Kim
 
AI + DevOps = Smart Automation with devseccops.ai.pdf
Devseccops.ai
 
Homogeneity of Variance Test Options IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
Hardware(Central Processing Unit ) CU and ALU
RizwanaKalsoom2
 
MiniTool Partition Wizard 12.8 Crack License Key LATEST
hashhshs786
 
MiniTool Partition Wizard Free Crack + Full Free Download 2025
bashirkhan333g
 
Alarm in Android-Scheduling Timed Tasks Using AlarmManager in Android.pdf
Nabin Dhakal
 
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
AEM User Group: India Chapter Kickoff Meeting
jennaf3
 
Wondershare PDFelement Pro Crack for MacOS New Version Latest 2025
bashirkhan333g
 

Building Distributed Systems