Monte Carlo
Übersicht¶
In diesem Projekt wird eine verteilte Berechnung verwendet, um eine Näherung für die Zahl Pi zu finden. Der Manager-Container sammelt Näherungswerte von Worker-Containern, die diese Berechnungen parallel mithilfe eines Monte-Carlo-Algorithmus durchführen. Der Durchschnitt dieser Werte ergibt die Näherung von Pi.
1. Manager-Server (Flask-Webserver)¶
Der Manager fungiert als zentraler Server und empfängt die von den Workern berechneten Pi-Schätzungen. Er speichert die Ergebnisse und bietet eine API an, über die der Durchschnitt aller eingegangenen Werte abgefragt werden kann.
manager.py
from flask import Flask, request, jsonify
app = Flask(__name__)
results = []
@app.route('/submit', methods=['POST'])
def submit_result():
data = request.json
result = data.get('pi_estimate')
if result:
results.append(result)
return jsonify({"message": "Result received"}), 200
else:
return jsonify({"message": "Invalid data"}), 400
@app.route('/average', methods=['GET'])
def get_average():
if len(results) == 0:
return jsonify({"average": None, "message": "No results yet"}), 200
average = sum(results) / len(results)
return jsonify({"average": average}), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
2. Worker-Skript mit Monte-Carlo-Algorithmus¶
Jeder Worker führt eine Monte-Carlo-Berechnung durch, um eine Näherung für Pi zu berechnen, und sendet das Ergebnis an den Manager.
worker.py
import random
import requests
import json
import time
def monte_carlo_pi(n):
inside_circle = 0
for _ in range(n):
x, y = random.random(), random.random()
if x**2 + y**2 <= 1:
inside_circle += 1
return (4 * inside_circle) / n
def send_result_to_manager(pi_estimate):
url = 'http://manager:5000/submit'
data = {'pi_estimate': pi_estimate}
headers = {'Content-Type': 'application/json'}
response = requests.post(url, data=json.dumps(data), headers=headers)
if response.status_code == 200:
print("Result sent successfully.")
else:
print("Error sending result.")
if __name__ == '__main__':
n = 1000000 # Number of points for Pi approximation
while True:
pi_estimate = monte_carlo_pi(n)
send_result_to_manager(pi_estimate)
time.sleep(5) # Wait 5 seconds before repeating
3. Docker-Setup¶
Dockerfile für den Manager¶
# Manager Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY manager.py /app/
RUN pip install flask
CMD ["python", "manager.py"]
Dockerfile für den Worker¶
# Worker Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY worker.py /app/
RUN pip install requests
CMD ["python", "worker.py"]
4. Docker Compose für den Swarm¶
Mit Docker Compose wird das gesamte Setup konfiguriert. Hier wird ein Overlay-Netzwerk definiert, das die Kommunikation zwischen Manager und Workern ermöglicht.
Docker Compose Datei: docker-compose.yml¶
services:
manager:
build:
context: ./manager
dockerfile: Dockerfile
ports:
- "5000:5000"
deploy:
replicas: 1
networks:
- pi_network
worker:
build:
context: ./worker
dockerfile: Dockerfile
deploy:
replicas: 2
networks:
- pi_network
networks:
pi_network:
driver: overlay
5. Schritte zur Ausführung¶
-
Erstelle die Dockerfiles für den Manager und Worker.
-
Baue die Images:
- Initialisiere den Swarm und starte die Services:
Die Worker senden nun ihre berechneten Pi-Werte an den Manager, und der Durchschnitt der Ergebnisse kann über den /average-Endpunkt abgefragt werden.
6. Kommunikation und Netzwerk¶
Docker Swarm nutzt ein Overlay-Netzwerk, um die Kommunikation zwischen Containern zu vereinfachen. Der Manager und die Worker können sich so über ihre Servicenamen finden, ohne eine explizite IP-Adresse festzulegen.