Skip to content

Commit

Permalink
greek language poolboy (elixirschool#858)
Browse files Browse the repository at this point in the history
  • Loading branch information
gemantzu authored and doomspork committed Dec 5, 2016
1 parent d3ea02f commit f1e89ca
Showing 1 changed file with 139 additions and 0 deletions.
139 changes: 139 additions & 0 deletions gr/lessons/libraries/poolboy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
---
layout: page
title: Poolboy
category: libraries
order: 2
lang: gr
---

Μπορείτε πολύ εύκολα να εξαντλήσετε τους πόρους τους συστήματός σας αν επιτρέψετε σε παράλληλες διεργασίες να τρέχουν ανεξέλεγκτα. Το Poolboy αποτρέπει την ύπαρξη του overhead δημιουργώντας μια λίστα με εργάτες για να περιορίσουν τον αριθμό των ταυτόχρονων διεργασιών.

## Γιατί να χρησιμοποιήσουμε το Poolboy;

Ας δούμε ένα συγκεκριμμένο παράδειγμα για λίγο. Σας έχει ανατεθεί να χτίσετε μια εφαρμογή αποθήκευσης πληροφοριών προφίλ σε μια βάση δεδομένων. Αν έχετε δημιουργήσει μια διεργασία για κάθε εγγραφή χρήστη, θα χρησιμοποιούσατε απεριόριστο αριθμό συνδέσεων. Και σε κάποιο σημείο αυτές οι συνδέσεις αρχίζουν να ανταγωνίζονται για τους περιορισμένους πόρους που είναι διαθέσιμοι στο διακομιστή της βάσης δεδομένων. Τελικά η εφαρμογή σας αρχίζει να εμφανίζει σφάλματα ορίου χρόνου και διάφορες εξαιρέσεις εξ' αιτίας του overhead από αυτό τον ανταγωνισμό.

Η λύση σε αυτό το πρόβλημα είναι η χρήση ενός σετ εργατών (διεργασίες) για να περιορίσουμε τον αριθμό συνδέσεων αντί να δημιουργούμε μια διεργασία για κάθε εγγραφή χρήστη. Τότε μπορείτε εύκολα να αποτρέψετε την εξάντληση των πόρων του συστήματος σας.

Εδώ έρχεται το Poolboy. Δημιουργεί μια λίστα εργατών που διαχειρίζονται από έναν `Supervisor` χωρίς καμμία ενέργεια από μέρους σας για να γίνει χειροκίνητα. Για την ακρίβεια υπάρχουν πολλές βιβλιοθήκες που χρησιμοποιούν το Poolboy στο εσωτερικό τους. Για παράδειγμα: η λίστα συνδέσεων της `postgrex` *(η οποία με τη σειρά της αξιοποιείται από την Ecto όταν χρησιμοποιούμε την psql)*, η `redis_poolex` *(Λίστα συνδέσεων Redis)* είναι μερικές από τις πιο δημοφιλείς βιβλιοθήκες που χρησιμοποιούν το Poolboy.

{% include toc.html %}

## Εγκατάσταση

Η εγκατάσταση είναι πανεύκολη με το mix. Το μόνο που πρέπει να κάνουμε είναι να προσθέσουμε το Poolboy σαν εξάρτηση στο `mix.exs` μας.

Ας δημιουργήσουμε μια εφαρμογή πρώτα:

```
$ mix new poolboy_app --sup
$ mix deps.get
```

Ας προσθέσουμε το Poolboy σαν εξάρτηση στο `mix.exs` μας.

```elixir
defp deps do
[{:poolboy, "~> 1.5.1"}]
end
```

Και ας προσθέσουμε το Poolboy στην εφαρμογή OTP μας:

```elixir
def application do
[applications: [:logger, :poolboy]]
end
```

## Οι επιλογές ρύθμισης

Πρέπει να γνωρίζουμε μερικά πράγματα για τις διάφορες επιλογές ρύθμισης ώστε να ξεκινήσουμε να χρησιμοποιούμε το Poolboy.

* `name`: το όνομα της λίστας. Το πεδίο δράσης μπορεί να είναι `:local`, `:global` ή `:via`.
* `worker_module:` η ενότητα που αναπαριστά τον εργάτη.
* `size:` το μέγιστο μέγεθος της λίστας.
* `max_overflow:` ο μέγιστος αριθμός εργατών που δημιουρούνται αν η λίστα είναι άδεια. (προεραιτικό)
* `strategy:` `:lifo` ή `:fifo`, ορίζουν αν οι ελεγχόμενοι εργάτες ορίζονται π΄ρωτοι ή τελευταίοι στη σειρά των διαθέσιμων εργατών. Η προεπιλογή είναι `:lifo`. (προεραιτικό)

## Ρυθμίζοντας το Poolboy

Για αυτό το παράδειγμα, θα δημιουργήσουμε μια λίστα εργατών που είναι υπέυθυνοι για το χειρισμό αιτήσεων υπολογισμού της τετραγωνικής ρίζας ενός αριθμού. Θα διατηρήσουμε το παράδειγμά μας απλό ώστε να εστιάσουμε στο Poolboy.

Ας ορίσουμε τις επιλογές ρύθμισης του Poolboy και ας το προσθέσουμε σαν εργάτης παιδί μέρος της εκκίνησης της εφαρμογής μας.

```elixir
defmodule PoolboyApp do
use Application

defp poolboy_config do
[{:name, {:local, :worker}},
{:worker_module, Worker},
{:size, 5},
{:max_overflow, 2}]
end

def start(_type, _args) do
import Supervisor.Spec, warn: false

children = [
:poolboy.child_spec(:worker, poolboy_config, [])
]

opts = [strategy: :one_for_one, name: PoolboyApp.Supervisor]
Supervisor.start_link(children, opts)
end
end
```

Το πρώτο πράγμα που ορίσαμε είναι οι επιλογές ρυθμίσεων για τη λίστα. Καθορίσαμε ένα μοναδικό `:name` για τη λίστα μας, ορίσαμε την `:scope` σε τοπική, και το `:size` της λίστας να είναι 5 εργάτες. Επίσης, σε περίπτωση που οι εργάτες μας είναι απασχολημένοι, ρυθμίζουμε τη δημιουργία δύο επιπλέον εργατών για να βοηθήσουν με το φόρτο, χρησιμοποιώντας την επιλογή `:max_overflow`. *(οι `overflow` εργάτες παύουν να υπάρχουν μόλις ολοκληρώσουν την εργασία τους.)*

Στη συνέχεια, προσθέσαμε τη συνάρτηση `poolboy.child_spec/3` στον πίνακα των παιδιών ώστε η λίστα εργατών να ξεκινάει με την εκκίνηση της εφαρμογή.

Η συνάρτηση `child_spec/3` δέχεται τρία ορίσματα: το όνομα της λίστας, τις ρυθμίσεις της λίστας και το τρίτο όρισμα που περνάμε στη συνάρτηση `worker.start_link`. Στην περίπτωσή μας είναι απλά μια άδεια λίστα.

## Δημιουργία Εργάτη

Η ενότητα εργάτη θα είναι ένας απλός GenServer υπολογισμού της τετραγωνικής ρίζας ενός αριθμού, που κοιμάται για ένα δευτερόλεπτο και τυπώνει το pid του εργάτη:

```elixir
defmodule Worker do
use GenServer

def start_link(_) do
GenServer.start_link(__MODULE__, nil, [])
end

def init(_) do
{:ok, nil}
end

def handle_call({:square_root, x}, _from, state) do
IO.puts "process #{inspect self} calculating square root of #{x}"
:timer.sleep(1000)
{:reply, :math.sqrt(x), state}
end
end
```

## Χρήση του Poolboy

Τώρα που έχουμε τον `Worker`, μπορούμε να δοκιμάσουμε το Poolboy. Ας δημιουργήσουμε μια απλή ενότητα που δημιουργεί ταυτόχρονες διεργασίες χρησιμοποιώντας τη συνάρτηση `:poolboy.transaction`:

```elixir
defmodule Test do
@timeout 60000

def start do
tasks = Enum.map(1..20, fn(i) ->
Task.async(fn -> :poolboy.transaction(:worker,
&(GenServer.call(&1, {:square_root, i})), @timeout)
end)
end)
Enum.each(tasks, fn(task) -> IO.puts(Task.await(task, @timeout)) end)
end
end

```
Αν δεν έχετε διαθέσιμους εργάτες στη λίστα σας, το Poolboy θα έχει μια λήξη ορίου χρόνου μετά το τέλος της περιόδου λήξης ορίου χρόνου (πέντε δευτερόλεπτα) και δεν θα δέχεται νέες αιτήσεις. Στο παράδειγμά μας, αυξήσαμε το προκαθορισμένο όριο λήξης χρόνου στο ένα λεπτό ώστε να επιδείξουμε πως μπορούμε να αλλάξουμε την προκαθορισμένη τιμή λήξης ορίου χρόνου.

Παρόλο που προσπαθούμε να δημιουργήσουμε πολλαπλές διεργασίες *(είκοσι στο σύνολό τους στο παραπάνω παράδειγμα)*, η συνάρτηση `:poolboy.transaction` θα περιορίσει το σύνολο των δημιουργημένων διεργασιών σε πέντε *(συν δύο εργάτες υπερχείλισης αν απαιτούνται)* όπως το ορίσαμε στις ρυθμίσεις μας. Όλες οι αιτήσεις θα χειριστούν από τη λίστα εργατών μας αντί να δημιουργείται μια νέα διεργασία για κάθε μια αίτηση.

0 comments on commit f1e89ca

Please sign in to comment.