1
1
# Ders 14: Asenkron Programlama
2
2
3
- Rust eşzamanlı _ (concurrent)_ programlama haricinde asenkron programlamayı da destekler. Asenkron programlama özellikle
4
- dosya I/O işlemleri, network operasyonları, zaman bazlı görevler _ (scheduled tasks)_ ve servis iletişimi gibi beklemeye
5
- neden olan süreçlerde CPU'nun idle kalmak yerine bahsedilen operasyonları icra etmesi için kullanılan bir yaklaşımdır.
6
- Rust bu ihtiyaca async ve await anahtar kelimeleri ile cevap verir. Rust tarafında asenkron programlama süreçleri
7
- genellikle defacto hale gelmiş çeşitli küfeler _ (crates)_ ile sağlanır. Tokio küfesi bunlar arasında en popüler
8
- olanlarındandır. Bunun sebebi async fn çağrıları sonucu dönen Future nesnelerini yönetecek hazır bir ortamın built-in
9
- olarak gelmemesidir .
3
+ Rust eşzamanlı _ (concurrent)_ programlama haricinde ** asenkron** programlamayı da destekler. Asenkron programlama
4
+ özellikle dosya I/O işlemleri, network operasyonları, zaman bazlı görevler _ (scheduled tasks)_ ve servis iletişimi gibi
5
+ beklemeye neden olan süreçlerde CPU'nun boşta kalması yerine bahsedilen operasyonları icra etmesi için kullanılan bir
6
+ yaklaşımdır. Rust bu ihtiyaca ** async** ve ** await** anahtar kelimeleri ile cevap verir. Rust tarafında asenkron
7
+ programlama süreçleri genellikle standart hale gelmiş çeşitli küfeler _ (crates)_ ile de sağlanır. ** Tokio** küfesi
8
+ bunlar arasında en popüler olanlarındandır. Bunun sebebi async fn çağrıları sonucu dönen Future nesnelerini yönetecek
9
+ hazır bir ortamı içermesidir .
10
10
11
11
## Thread vs Async/Await
12
12
@@ -26,10 +26,11 @@ aşağıdaki tabloda özetlenmiştir.
26
26
## Örnekler
27
27
28
28
Asenkron programlama konseptini anlamanın en iyi yolu gerçek hayat örnekleri üzerinden ilerlemektir. Bir sunucudaki
29
- işlemci, bellek ve disk kullanım durumlarını anlık olarak takip eden bir sistem programı geliştirmek istediğimizi
30
- düşünelim. Burada donanım bazında çalışan fonksiyonellikler olduğunu ifade edebiliriz. Senkron bir okuma yerine asenkron
31
- olarak bu değerlerin okunması sağlanabilir. Aşağıdaki örnek kod parçasında bu durumu tokio küfesi kullanılarak simüle
32
- edilmektedir.
29
+ işlemci, bellek ve disk kullanım durumlarını anlık olarak takip eden bir sistem aracı geliştirmek istediğimizi
30
+ düşünelim. Bu senaryoda donanım bazında metrik ölçümleri yapan fonksiyonellikler olduğunu ifade edebiliriz. Senkron bir
31
+ okuma yerine asenkron olarak bu değerlerin okunması sağlanabilir. Bir başka deyişle sistem metrikleri eş zamanlı
32
+ çalıştırılacak görevler haline getirilip birbirlerinden bağımsız ve beklemeden işletilebilir. Aşağıdaki örnek kod
33
+ parçasında bu durum tokio küfesi kullanılarak simüle edilmektedir.
33
34
34
35
``` rust
35
36
use rand :: Rng ;
@@ -73,9 +74,9 @@ fn get_metric() -> f64 {
73
74
```
74
75
75
76
Örnek kod sembolik olarak işlemci, bellek ve disk kullanım oranlarını takip eden fonksiyonellikleri ele alır. Bu tip
76
- işlevler senkron çalışmak yerine eş zamanlı olarak işletilebilirler. task::spawn çağrısı bu görevleri başlatmak için
77
- kullanılır. fetch_metrics metodu ** async** keyword'ü ile imzalandığından task::spawn tarafından kullanılabilir. tokio
78
- küfesinden gelen spawn metodunun tanımı aşağıdaki gibidir.
77
+ işlevler senkron çalışmak yerine eş zamanlı olarak işletilebilirler. ** task::spawn** çağrısı bu görevleri başlatmak için
78
+ kullanılır. ** fetch_metrics** metodu ** async** keyword'ü ile imzalandığından ** task::spawn** tarafından kullanılabilir.
79
+ ** Tokio ** küfesinden gelen spawn metodunun tanımı aşağıdaki gibidir.
79
80
80
81
``` rust
81
82
pub fn spawn <F >(future : F ) -> JoinHandle <F :: Output >
@@ -85,15 +86,16 @@ where
85
86
{}
86
87
```
87
88
88
- Dikkat edileceği üzere JoinHandle nesnesi Future ve Send trait'lerini implemente eden , statik yaşam ömrüne sahip bir
89
- enstrümandır . Future trait esasında poll tekniğine göre asenkron olarak başlatılan operasyon tamamlandığında devreye
90
- girileceğini ifade eder. Burada thread'ler arası haberleşme de söz konusudur ve unsafe olan Send trait bunu garanti
91
- eder. Kısacası elimizde asenkron olarak başlatılan operasyonlar ve bu operasyonlar tamamlandığında devreye giren, diğer
92
- thread'leri kesintiye uğratmayan Handler türleri vardır. Tüm JoinHandle nesnelerinin işlerinin tamamlanmasını beklemek
93
- için yine Join mekanizması kullanılır.
89
+ Dikkat edileceği üzere ** JoinHandle** nesnesi ** Future** ve ** Send** trait'lerini uygulayan , statik yaşam ömrüne
90
+ sahip bir yapıdır . Future trait, poll tekniğine göre asenkron olarak başlatılan operasyon tamamlandığında
91
+ devreye girileceğini ifade eder. Burada thread'ler arası haberleşme de söz konusudur ve ** unsafe** olan ** Send** trait
92
+ bunu garanti eder. Kısacası elimizde asenkron olarak başlatılan operasyonlar ve bu operasyonlar tamamlandığında devreye
93
+ giren, diğer thread'leri kesintiye uğratmayan ** Handler** nesne örnekleri vardır. Tüm ** JoinHandle** nesnelerinin
94
+ işlerinin tamamlanmasını beklemek için yine ** Join** metodu kullanılır.
94
95
95
- Örnekte kullanılan fetch_metrics fonksiyonu metrikler üretildikçe bu değerleri transmitter araclığı ile bir kanala
96
- bırakır. Kanala bırakılan bu bilgiler başka bir task içerisinden receiver nesnesi ile yakalanır ve terminale basılır.
96
+ Örnekte kullanılan ** fetch_metrics** fonksiyonu metrikler üretildikçe bu değerleri ** transmitter** araclığı ile bir
97
+ kanala bırakır. Kanala bırakılan veriler başka bir task içerisinden ** receiver** nesnesi ile yakalanır ve terminal
98
+ ekranına basılır.
97
99
98
100
Eş zamanlı görevlerin sık kullanıldığı bir başka senaryo ise, web servislerine gönderilen taleplerle ilgilidir.
99
101
Aşağıdaki örnek kod parçasında bir web api hizmetine örnek talepler gönderilmekte ve bu talepler asenkron çalışan
@@ -130,14 +132,15 @@ async fn fetch_data_async(url: &str) -> Result<String, reqwest::Error> {
130
132
}
131
133
```
132
134
133
- Web Api türünden servisler HTTP protokolünün Get, Post, Put, Delete, Patch gibi metotlarını kullanan Restful mimariye
134
- göre tasarlanmış hizmetlerdir. Genellikle JSON türünden veriler kullanırlar. Örnekte kullanılan dummy servis ile olan
135
- iletişimi kolaylaştırmak için reqwest isimli bir küfe kullanılmıştır. task_a, task_b ve task_c nesneleri ile söz konusu
136
- servise üç ayrı talep yapılır. Tüm bu talepler fetch_data_async isimli asenkron fonksiyon tarafından eş zamanlı olarak
137
- ele alınır. Api servisinden HTTP Get metodu ile veri çekme işi reqwest'in get metodu ile gerçekleştirilir ki bu metot da
138
- asenkron olarak çağrılabilir. await çağrısı söz konusu fonksiyona ait Future'un bir sonuç elde edene kadar beklenmesini
139
- söyler ancak bu diğer thread'leri engelleyen bir durum değildir.
140
-
141
- Servis haberleşmeleri ağ ortamlarında gerçekleşen süreçler olduğundan ana akışı bekletmeye neden olurlar. Cevap süreleri
142
- çok yüksek olsa dahi eş zamanlı olarak sayısız talebin ele alındığı durumlarda servis görevlerini asenkron başlatmak
143
- tercih edilen bir çözümdür. Bu mantık bir web sunucusu yazarken de geçerlidir.
135
+ Web Api türünden servisler ** HTTP** protokolünün ** Get, Post, Put, Delete, Patch** gibi metotlarını kullanan ** Restful**
136
+ mimariye göre tasarlanmış hizmetlerdir. Servis haberleşmesinde genellikle ** JSON** türünden veriler kullanırlar. Örnekte
137
+ kullanılan dummy servis ile olan iletişimi kolaylaştırmak için ** reqwest** isimli bir küfe kullanılmıştır. ** task_a** ,
138
+ ** task_b** ve ** task_c** nesneleri ile söz konusu servise üç ayrı talep yapılır. Tüm talepler ** fetch_data_async**
139
+ isimli asenkron fonksiyon tarafından eş zamanlı olarak ele alınır. Api servisinden ** HTTP Get** metodu ile veri çekme
140
+ işi reqwest'in ** get** metodu ile gerçekleştirilir ki bu metot da asenkron olarak çağrılabilir. ** await** çağrısı söz
141
+ konusu fonksiyona ait ** Future** nesnesinin bir sonuç elde edene kadar beklenmesini söyler ancak bu diğer iş
142
+ parçacıklarının _ (thread)_ çalışmasını engelleyen bir durum değildir.
143
+
144
+ Servis haberleşmeleri ağ ortamlarında gerçekleşen süreçler olduğundan ana kod akışını belirsiz sürelerde bekletmeye
145
+ meğillidir. Cevap süreleri çok yüksek olsa dahi eş zamanlı olarak sayısız talebin ele alındığı durumlarda servis
146
+ görevlerini asenkron başlatmak tercih edilen bir çözümdür. Bu mantık bir web sunucusu yazarken de geçerlidir.
0 commit comments