Apache PredictionIO kullanarak nasıl Recommendation Engine yaparız ?

Apache PredictionIO®, geliştiricilerin ve veri bilim adamlarının herhangi bir makine öğrenme görevi için tahmine dayalı motorlar oluşturması için state-of-the-art açık kaynaklı bir Makine Öğrenim Sunucusudur.
Recommendation Engine diyince herkesin aklına bişeyler geliyodur elbet. Ne olduğunu anlatmaktansa senaryo ile anlatmak bence daha doğru bir yaklaşım olarak geliyor. Uzun uzun ve teknik olarak bir sürü açıklaması mevcut ama gerçek hayatta karşımıza geldiği anlarla daha açıklayıcı oluyor

Tam olarak Homer’ın yaptığı gibi bir ürün aldığımda bu ürünle alakalı olabilecek bir ürünün önerilmesi aslında olan. Burda esas alınan farklı faklı parametreler olabilir( View, Buy, Rate vb)

Aynı şekilde bir müzik türü dinliyorum ve Spotify amca diyorki abime AC/DC’ den bişeyler daha vereyim. Tabi iyiyse biz de sar hadi diyoruz 😂
Ne kadar çok veriniz varsa o kadar sağlam öneri geliyor haliyle.
Bu kadar teknik olmayan bilgi yeter gelelim asıl olaya 😎
Anlattıklarımı Google Cloud üzerinden anlatacağım. Herhangi bir provider’da olur. (İşimiz VM Instances ile olduğundan)

- Event Server : Yukarıda da anlatıldığı gibi Web, Mobile … gibi kanallardan gelen datayı PredictionIO’ ya verdiğimiz yapı. Buraya gelen veriyi click stream verisi olarak nitelendirebiliriz. (Product View, Purchase, Basket Add&Remove…) Gelen datada kayıp olmaması için önünde Kafka gibi bir message queue dinleyen bir uygulama olması güzel olur.
- Prediction Server(Engines) : Spark MLlib ile train yapıldıktan sonra train edilen verinin deploy edildiği yer. Burası aynı zaman client’dan gelen requestleri karşılayan taraf olacak. Yani en yüksek trafik bu kısımda olacağı için önüne load-balancer koyup n cluster yapmakta fayda var.
Kong gibi bir API Gateway güzel olabilir. Bu sayede pluginlerini kullanarak Traffic Control, Authentication vb gibi uğraştırıcı işleri zahmetsizce halledebilirsiniz.
Kurulum aşamasına geçiyoruz. PredictionIO aslında Big Data dünyasından bildiğimiz Apache Ekosistemin Core denebilecek toollarını efektif şekilde kullanarak bize yönetilebilir bir yapı veriyor.
- Apache Hadoop (Optional)
- Apache Spark
- Java SE Development Kit 8
Storage için :
- PostgreSQL
veya
- MySQL
veya
- Apache HBase
- Elasticsearch
istiyor.
Bu makalede Stack aşağıdaki şekilde olacak :
- Apache Hadoop 2.6.5 (3 cluster → 1 master, 2 slave)
- Apache Spark 2.1.1 for Hadoop 2.9 (3 cluser → 1 master, 2 worker)
- Apache HBase 1.2.6 (3 cluster → 1 master)
- Elasticsearch 5.6.15
Hadoop, Spark ve Hbase’in nasıl Distributed hale getirilebileceği ile ilgili yazılar mevcut. Fakat sürümler arası sorunlar olduğundan yada karşılaştığım sorunlarla karşılamamak adına hepsinin kurulumuna değineceğim o yüzden uzun bir yazı olacak şimdiden uyarayım isteyenler bu kısmı geçebilir. 🤓
Sürümleri rastgele olsun diye değil uyumlu oldukları için yazdım :)
Bu kurulumları yok canım ben zahmet çekmeyeceğim bunun kolayı yok mu arkadaş derseniz. Cloudera ‘ ya bakmanızı öneririm. Cloudera ile makineleri verip buraya 3 cluster spark, hadoop vb olsun diye verebiliyorsunuz.
Hazırlık Aşaması
1-) Linux dağıtımı olarak CentOS’u seçtim. Burada wget, screen vb gibi paketleri kurduğumuzu varsayıyorum. SELinux’u kapatarak başlıyoruz.
Sonrasında tabiki de JAVA kurmamız lazım. Bunu yazmıyorum rpm’i scp ile sunucunuza atarak kurulum yapabilirsiniz. Son demelerinde Oracle’da auth olayları yüzünden wget yapamamıştım.
2-) Makinelerin birbirleri arasında ssh yapabilmesi gerekiyor. Bu yüzden predictionio’nun kısaltımı olan pio adında bir user açıyoruz.
sudo adduser --shell /bin/bash pio
Sonrasında ise ilgili user’ geçip ssh key’i oluşturmamız lazım.
sudo su pio
ÖNEMLİ: Sadece bir makinede yapılacak ve diğer makinelere kopyanalacak →
3-) Herhangi bir makinede olduğumuzu varsayalım.
ssh-keygen
ile ssh key’imizi oluşturuyoruz.
Diğer makinelere bu oluşturduğumuz pub ve private’ları kopyalamamız lazım. (Birbirleri ile ssh yapabilmeleri için)
pub dosyamızın içinde son parametre olarak kullanıcı yazar oraya pio yazıyoruz.
ssh-rsa XXXX pio
şeklinde olması lazım.
4-) ~/.ssh altında authorized_keys adında dosya oluşturuyoruz ve pub key’imizi buraya kopyalıyoruz. Gerekli izinleri de veriyoruz.
cd ~/.ssh
cat id_rsa.pub > authorized_keys
chmod 400 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/authorized_keys
Bu oluşturduğumuz pub(id_rsa.pub) ve private(id_rsa) dosyalarını bir yere not alalım.
Diğer makinelerde yukarıdaki 2 adımıda uyguluyoruz. Sonrasında ise not aldığımız pub ve private key ile burda oluşanları değiştiriyoruz.
Sonrasında 4. adımı uyguluyoruz. Bunu tüm makinelerde uyguluyoruz. Bu yaptıktan sonra şu şekilde test edebilirsiniz.
machine1 diye makineye bağlı olduğumuzu varsayalım(pio user’ında iken)
ssh pio@machine2
yaptığımızda sorunsuz bir şekilde bağlanmamız gerekiyor.
Bu spark, hadoop gibi uygulamalarda birbirleri ile haberleşmeleri için gerekli(Master-slave ilişkisi)
Hadoop ile başlayalım.
Google Cloud Compute Engine’de VM Instances’da 3 tane makine oluşturalım. Makine adları hadoop-master, hadoop-slave01, hadoop-slave02 olabilir. Bu üç makineye’ de Hazırlık Aşaması işlemlerini yaptığımızı varsayıyorum.
Bununla ilgili bir çok makale mevcut o yüzden sonrasında bir yazı yazabilirim fakat ufak bir aramayla multi cluster nasıl yapılacağına bakabilirsiniz.
Spark ile devam edelim.
Google Cloud Compute Engine’de VM Instances’da 3 tane makine oluşturalım. Makine adları spark-master, spark-worker01, spark-worker02 olabilir. Bu üç makineye’ de Hazırlık Aşaması işlemlerini yaptığımızı varsayıyorum.
Bununla ilgili bir çok makale mevcut o yüzden sonrasında bir yazı yazabilirim fakat ufak bir aramayla multi cluster nasıl yapılacağına bakabilirsiniz.
Hbase ile devam edelim.
Google Cloud Compute Engine’de VM Instances’da 3 tane makine oluşturalım. Makine adları hbase-master, hbase-slave01, hbase-slave02 olabilir. Bu üç makineye’ de Hazırlık Aşaması işlemlerini yaptığımızı varsayıyorum.
Bununla ilgili bir çok makale mevcut o yüzden sonrasında bir yazı yazabilirim fakat ufak bir aramayla multi cluster nasıl yapılacağına bakabilirsiniz.
Elasticsearch ile devam edelim.
Google Cloud Compute Engine’de VM Instances’da 1 tane makine oluşturalım. Makine adları elasticsearch-master olabilir. Bu makineye’ de Hazırlık Aşaması işlemlerini yaptığımızı varsayıyorum. Burası modellerin adlarının ve predictionio’nun gerekli olan config’leri sakladığı yer.
Normalde predictionio’ nun kendi sitesinde cluster şeklinde değilde tek makine üzerinden anlatılmış herşey.
Burada Event Server ve Prediction Server diye ikiye böleceğiz. Prediction Serveryoğun trafik olacağı için önüne load balancer koyup aynı makinelerden koymak akıllıca olacaktır. Google Cloud load balancer kullanabilirsiniz.(Kullanımı gayet rahat)
Event Server ile başlayalım.
Herhangi bir klasör oluşturalım ve içine predictionio.tar.gz ‘ yi açalım.
sudo mkdir -p /app/downloads
cd /app/downloadssudo wget http://apache.mirrors.pair.com/predictionio/0.14.0/apache-predictionio-0.14.0-bin.tar.gzsudo tar -xzf apache-predictionio-0.14.0-bin.tar.gz
Sonrasında açılan klasörü app klasörüne taşıyalım.
sudo mv apache-predictionio-0.14.0 ../app
Yukarıda yaptığımız şekilde hadoop, spark, hbase’i app klasörü altına çıkaralım. (Aynı işlem olduğu için tek tek yazmadım.) Burada önemli olan nokta sürümlerin yukarıda belirttiğim gibi olması.
Klasörün içinde conf/pio-env.sh’ı düzenlememiz lazım.
Sonrasında eğer herşeyi düzgün bir şekilde yapılandırabildiysek artık model eğitimi ve deploy’una geçeceğiz.
Predictionio, tüm bu yapıları templateler üzerinden inşa eder.
Template derken buradaki kasıt model oluşturulurken hangi algoritmanın kullanılacağı demek.
Templateleri yukarıdaki linkten inceleyebilirsiniz.
Burada Official olan templateler var. Bunları biraz açayım.
Sitelerde gezinirken sizde şu şekilde öneriler görmüşsünüzdür. →
- Bu Ürüne Bakanlar Bunları da incelediler
- Bu Ürünü Alanlar Bunları da aldılar
- Hoşuna Gidebilecek Ürünler
- Sizin için Seçtiklerimiz
- …
Aslında buradaki olanların hepsi birer algoritma. Spark Mllib’de ise yaygın olarak Collaborative filtering kullanılıyor. Bunu da alternating least squares (ALS) ile yapıyor.
Bu örneğimizde Similar Product Engine template’ini kullanacağız. Yani kullancıların hareketlerine göre yapılan view, buy, … eventlerine göre verdiğimiz ürüne karşılık istediğimiz miktarda öneri verebilecek bir algoritma. Başlığını “Bu Ürüne Bakanlar Bu Ürüne de baktı” diye koyabilirsiniz.
Bu algoritmalar Scala ile yazılıyor ve isterseniz sizde bir algoritma geliştirip yada varolan algoritmayı Scala ile port edip burada kullanılmasını sağlayabilirsiniz.(Çok da güzel olur.)
Bunları düzenledikten sonra pio ‘yu PATH’e eklememiz lazım.
PATH=$PATH:/home/yourname/PredictionIO/bin; export PATH
Sonrasında artık yeni bir app oluşturmamız lazım.
$ pio app new MyApp1
ile oluşturabilirsiniz.
Bu komut çalıştıktan sonra yeni bir accessKey verecek bu key api ile event gönderirken lazım olacak bir yere not ederseniz yararlı olur.
Şimdi sırada ürün beslemeye geldi sıra. Burada biraz event tiplerinden bahsetmek istiyorum.
Örneğim bir product view event’i beslemek istiyorsunuz.
Bunun için ilk başta ilgili user ve ürünü beslemeniz lazım. Sonrasında ise X ürüne Y user’ı baktı veya satın aldı isimli event’i gönderebiliriz.
Aşağıda bu funnel’ı görebilirsiniz. (cURL ile anlatım)
Şöyle bir güzellikte var. Bir ürün beslediniz farklı bir kullanıcıda aynı ürüne baktı eğer entityId ‘ leri aynı verirseniz üzerine yazılıyor yeni kayıt olarak gelmiyor. Her gelen ürüne ait değişiklik tutuluyor.
Eventleri bu şekilde beslediğimizi varsayıyorum. Bunların client’dan nasıl besleneceği ile bilgiler de vereceğim. Bunun için bir sdk yazmanız gerekiyor. Kullanıcı herhangi bir product sayfasına geldiğinde bu ürüne ait ad, fiyat vb bilgilere ulaşabilmeniz gerekiyor. Bunu tag-manager veya dom üzerinden alabilirsiniz yada window’a basılan herhangi bir objeden alabilirsiniz.
JS SDK ile ilgili de bir makale yazacağım. (Hem request atan hem de gelen response’u template engine’e giydiren ve slider şeklinde gösterebilen bir yapı)
Tabi bu eventleri cloud kısmında karşılayan bir makine olması lazım. Burası yoğun bir şekilde trafik alacağı için bazı çözümler düşünmeniz gerekiyor.
Client’dan atılan requestleri predictionio’nun istediği payload ile de atabilirsiniz yada arada geçit olan bir app yazıp predictionio api larını kullanarak atabilirsiniz.(Java, Python, Ruby, PHP gibi destekleri mevcut)
Artık ileri aşamaya geçebiliriz.
- Build → Template’i build edip bir jar çıkarır.
- Train → Oluşturalan template’i kullanıp Spark MLlib ile modelimizi train eder ve bunu Hadoop’a kaydeder.
- Deploy → Oluşturulan bu modeli sorgulanabilen bir hale getirir ve default olarak 8000 port’u olacak şekilde dışarı açar. (Makinenin 8000 portunun yada verdiğiniz portunun dışarı açık olduğudan emin olmanız lazım.)
aşamaları var. Tüm aşamaların çeşitli parametreleri var bunları da anlatacağım. (Kritik öneme sahip özellikle Spark için)
Burada artık yeni bir makine oluşturmamız lazım. Önceden bahsettiğim gibi Predictionserver olacak burası ve modelimizi burda train, build ve deploy edeceğiz.
Tüm makinelerde yapılması gerekenleri üstte belirtmiştim. Onları yaptıktan sonra Eventserver makinesinde yaptığımız adımların aynısını yapıyoruz
- pio user’ı oluşturma
- predictionio’u indirme
- pio’yu path’e ekleme
Bu makine Eventserver makinesinden farklı olarak template’i de barındıracak.
Bunu event besleme ve diğer kısımları ayırmak için yaptık. Kendi sitesinde herşeyi tek makine üzerinden anlatıyor fakat bu uzun soluklu pekte stabil olmayacaktır. Makinede herhangi bir sorunda örneğin event besleme ile problem olup makine düştüğünde bizim recommendation verdiğimiz enginemizde devre dışı kalacaktır. Tıpkı monolithic yapı micro-service mimarisi olarak düşünebilirsiniz.
Yukarıdaki linkte aslında güzel bir şekilde anlatılmış. Fakat burda dikkat edilmesi gerekenleri ve başıma gelenleri anlatacağım.
git clone https://github.com/apache/predictionio-template-similar-product.git
ile herhangi bir yere template’i indiriyoruz.
Bu template default olduğu için bizim istediğimiz şekilde response gelmeyecektir. Bunun için kendi istediğimiz şekilde düzenlememiz lazım.
Örnek vermek gerekirse;
E-commerce bir siteye öneri yapacağız burada sizin de öngörebileceğiniz üzere Ürün ismi, fiyatı, indirimli fiyatı, resmi, linki gibi bilgileri gerekir. Bu nitelikler artırılabilir tabi.
Bu template’in olduğu klasöre girelim ve src/main/scala/ dizinine gidelim.
Yukarıdaki linkte nereleri değiştirmemiz gerektiğini belirtiyor.
Örneğin ürün resmi de istiyorsak DataSource.scala, Engine.scala, ALSAlgorithm.scala dosyalarında image parametresini eklememiz lazım.
Ne şekilde eklemeniz gerektiğini önceki eklenenlere bakarak kolayca kavrayabilirsiniz. Bu işlemleri gerçekleştirdikten sonra artık dönen response’da istediğimiz properties’lerde gelmiş olacak.
$ pio build --verbose
komutu ile template’i build alalım. ( — verbose bu işlem yapılırken oluşan hata veya yapılan işlemi detaylı görmenizi sağlar.)
Düzgün bir şekilde build işlemi tamamlanırsa “[INFO] [Console$] Your engine is ready for training.” şeklinde info gelir.
pio train
Bu komut çok önemli çünkü en sık hatanın olduğu yer burası çünkü yapılan işlem büyük matrisler üzerinde olduğu için RAM’e fazlasıyla ihtiyaç duyuyor burada verilen parametreler “Java heap space error” yada diğer memory hatalarından kaçınmamızı sağlayacak.
Şimdi parametrelerine değineceğim biraz.
pio help train
ile pio’nun kendi komutlarına bakabilirsiniz.
Bizi burda daha fazla ilgilendiren kısım ise Spark ayarlarını verebildiğimiz yerleri çünkü train kısmı ile Spark ilgilendiği için burası önemli. Ayarları Spark makinesi kurarkende bu ayarları verebilirsiniz. Predictionio’nun burada yaptığı iş spark-submit komutuna parametre olarak vermek.
pio train -- --master spark://spark-master:7077 --driver-memory 24G --executor-memory 14G --num-executors 4 --executor-cores 4

Amazon tarafından best practiceler aşağıdaki şekilde →
spark.executor.memory
– Size of memory to use for each executor that runs the task.spark.executor.cores
– Number of virtual cores.spark.driver.memory
– Size of memory to use for the driver.spark.driver.cores
– Number of virtual cores to use for the driver.spark.executor.instances
– Number of executors. Set this parameter unlessspark.dynamicAllocation.enabled
is set to true.spark.default.parallelism
– Default number of partitions in resilient distributed datasets (RDDs) returned by transformations likejoin
,reduceByKey
, andparallelize
when no partition number is set by the user.
spark.executor.cores hesabı için →
Assigning executors with a large number of virtual cores leads to a low number of executors and reduced parallelism. Assigning a low number of virtual cores leads to a high number of executors, causing a larger amount of I/O operations. Based on historical data, we suggest that you have five virtual cores for each executor to achieve optimal results in any sized cluster.
For the preceding cluster, the property spark.executor.cores
should be assigned as follows: spark.executors.cores = 5 (vCPU)
spark.executor.memory hesabı için için aşağıdaki hesabı kullanabilirsiniz →
Number of executors per instance = (total number of virtual cores per instance — 1)/ spark.executors.coresNumber of executors per instance = (48 - 1)/ 5 = 47 / 5 = 9 (rounded down)
spark.driver.memory hesabı için aşağıdaki hesabı kullanabilirisiniz →
spark.driver.memory = spark.executors.memory
spark.default.parallelism hesabı için →
spark.default.parallelism = spark.executor.instances * spark.executors.cores * 2
spark.default.parallelism = 170 * 5 * 2 = 1,700
pio train kullanımında sonuna conf koymanız gerekiyor.
—-conf spark.sql.shuffle.partitions=12 --conf spark.default.parallelism=12
Açıkçası biraz deneme yanılma ile öğreniyoruz core’u ne kadar vermeliyim ram ne kadar olmalı çünkü verinin nasıl dağıldığı direkt olarak süreyi etkiliyor.
Train işlemi bittiğinde engineInstanceId adlı bir değer veriyor bunu not etmenizde fayda var.
Daha sonrasında bu train edilmiş modeli çıkar derken deploy command’ına parametre olarak verebiliyoruz.
Şimdi de train edilmiş uygulamamızı deploy etmeye geldi sıra.
Burdaki komutlarda çok önemli isterseniz pio deploy help ile kontrol edebilirsiniz.
pio deploy --event-server-ip eventserver --port 8000
Buradaki eventserver uygulamayı oluşturduğumuz sunucu demek.
Eğer başarılı şekilde yaptıysanız
“[INFO] [MasterActor] Engine is deployed and running. Engine API is live at http://0.0.0.0:8000.” şeklinde info gelecektir.
— engine-instance-id AWwjSam9IzDPjLq3ZMAM
ile model id’si verebilirsiniz. (Train adımında oluştuğunu anlatmıştım.)
cURL yada herhangi bir şey ile eğitilmiş modelinizi sorgulayabilirsiniz.
curl -H "Content-Type: application/json" \
-d '{ "items": ["i1"], "num": 10}' \
http://predictionserver:8000/queries.json
Şu şekilde response gelecektir →
{"itemScores":[{"item":"i21","score":1.1153550716504106},{"item":"i14","score":1.0773502691896257},{"item":"i26","score":1.0773502691896257},{"item":"i39","score":1.0773502691896257},{"item":"i44","score":1.0773502691896257},{"item":"i45","score":0.7886751345948129},{"item":"i47","score":0.7618016810571367},{"item":"i9","score":0.7618016810571367},{"item":"i28","score":0.7618016810571367},{"item":"i6","score":0.7618016810571367}]}
Bu predictionio’nun default örneği yukarıdaki şekilde template’i değiştirirseniz burada onlarda gelecektir(image, price vb…)
Dilerseniz burada predictionserver önüne bir app yazarak direkt istek atmak yerine SDK kullanarakta yapabilirsiniz.
Oluşabilecek hatalar ve çözümleri
- Deploy yaparken memory hatası geliyor
Çözümü gayet basit ilgili makinenin ram’ ini artırıyoruz ve driver-memory’ i belirtiyoruz. Çünkü belirtmezsek default olarak atandığı ram ile uygulamayı deploy etmeye çalışıyor ve meşhur cannot allocate memory’ (errno=12) hatasını alıyoruz
pio deploy --event-server-ip eventserver01 --port 8008 -- —-driver-memory 8G
- Deploy ederken No Space left hatası geliyor
Makinenin eğer boot diski yeterince büyük değilse bu hata ile karşılaşabilirsiniz. Bu durumda disk’i artırarak sorunu çözebiliyorsunuz.
- Elasticsearch’de ulimit hataları
/etc/security/limits.conf dosyasına aşağıdaki satırı eklemeniz ve makineyi yeniden başlatmanız gerekiyor.
elasticsearch - nofile 65535
- Elasticsearch heap space hataları
/elastichsearchpath/conf /jvm.options dosyasında -Xmx2g ve -Xms2g değerlerini artırmalısınız. Burada 2g → 2gb bellek ayırarak başlat anlamına geliyor.
- Train esnasında bazı stagelerde hiç bir hata vermeden train bittiği zamanlarda
Burada başıma şu şekilde bir şey geldi herhangi bir log’da yazmamasına rağmen deneme yanıma yoluyla bu sorunun scala versiyonu yüzünden olduğunu gördüm. Bunu için size tavsiyem 2.11.12 sürümünü indirmeniz. Bu durum direkt olarak build’i etkiliyor scala’yı yükledikten sonra tekrar build alıp train etmeyi denemelisiniz.
- Build esnasında oluşan sbt hataları
Burada tamamen yukarıdaki gibi sürümlerden oluşan bir sorun var eğer eski bir template kullanıyorsanız hatalar ortaya çıkıyor. build.sbt ve project/build.properties ve project/assembly.sbt ‘de olan sürümleri incelemelisiniz.
…
Optimizasyon ve Yararlı Araçlar
- Grafana
Burada en iyi arkadaşımız olacak kendisi. Bir makine oluşturup buraya grafana’yı ayağa kaldırıp tüm makinelere node_exporter kurarsanuz iyi bir şekilde monitör edebilirsiniz.

- Jenkins
Hem automated işler için hem de schedule işler işimizi çok kolaylaştırıyor. Jenkinsi herhangi bir commit atıldıktan sonra testlerden geçip build alıp deploy etmesi için ayarlayabilirsiniz. (GitHub hook trigger for GITScm polling ) Bunun için plugini kurmanız lazım.
Bunun yanı sıra modelleri sırası ile train edip deploy eden bir yapı yapmamız gerekiyor sürekli olarak bunu el ile yapamayız bunun için scriptler yazmamız gerekiyor. Hatta spark makineleri büyük makineler olduğundan cloud ortamında çalışıyorsanız bunların sürekli açık olmasını istemeyiz. Bunun için Cloud providerların SDK’larını kullanıp sadece train edileceği zaman makinelerin açılmasını sağlayabilirsiniz.
Yandaki şekilde train edebiliriz.
Yandaki şekilde deploy edebiliriz. Burada önemli olan nokta büyülü screen komutunda bunu daha detaylı anlatacağım.
Yandaki şekilde makineleri kapatabiliriz.
Sonrasında ise jenkins’de shell komutu çalıştırabiliriz.
Bunları ayarladıktan sonra schedule için cron expression girmeniz gerekiyor.
Örnek olarak 6 saatle bir çalışmasını istiyorsanız H H/6 * * * ayarlayabilirsiniz.
- Screen
Buna ayrı olarak değinmek istedim çünkü model deploy ettiğimizde o ekranın deatach olması gerekiyor. Yani o ekranın arka planda çalışmaya devam etmesi gerekiyor. Bunu yapmazsanız makineden çıktığınızda o process’de duracaktır. nohub olarakta tanımlayabilirsiniz fakat screen ile bunları kontrol etmek kolay olduğu için bunu kullandım.
screen -S pio
komutu ile pio ismi ile bir screen açıyoruz. İsmi sürekli aynı veriyorum çünkü her komutu çalıştırdığımda yeni bir tane oluşturuyor bunu istemiyorum o yüzden
screen -S pio -X quit
ile çıkabiliyoruz yada varsa oluşturma diyebiliriz. Tekrar screen oluşturduğumuzda normalde (ctrl + a + d) tuş kombinasyonuna basmamız gerekiyor bunu tabiki de yapmayacağız. Onun için kendi kendine deatach olması ve istediğimiz komutu çalıştırması için aşağıdaki komutu kullanabiliriz.
screen -S pio -d -m pio deploy --event-server-ip eventserver01
Böylece her schedule zamanlarında screen açıp uygulamamız(pio deploy) arka planda çalışmaya devam etmiş olabilecek.
- Spring Actuator ve Load Balancer
n tane predictionserver elimizde var diyelim ve makinelerden biri düştüğünde diğerlerinden hizmet vermeye devam vermemiz gerekiyor. Bunun için Spring’in kolayca health check yapmanıza izin veren bir tool’u devreye giriyor.
Sonrasında ise dışarıya açık tek bir endpoint’imiz olduğunu varsayalım Load Balancer olarak burada Google Cloud Load Balancer kullanacağım. n makinenide Health Check endpointlerini yazıyoruz ve tüm makinelerin önüne bu oluşturduğumuz load balancer’ı koyuyoruz. Eğer herhangi bir makine down olmuşsa Load Balancer direkt olarak trafiği diğer makinelere veriyor. Böylece kullanıcılara nurtopu gibi bir 500 status code’lu bir ekran göstermemiş oluyoruz. :)
- Spring Cache
Predictionserver makineleri yoğun bir şekilde istek aldığından bir cache mekanizması olmasa vah halinize :)
Spring Cache kullanarak predictionserver’ a direkt istek atmak yerine SDK ‘ini kullanarak bir Spring Boot uygulaması yazdım. Bu uygulamada ise zaten kullanıcılar sürekli olarak product gezdiği için productId ler tekrar etmeye başlayacaktır. Bununda önüne aynı productId’yi cacheleyecek şekilde bir mekanizma ile response time’ı düşürebilirsiniz. View modeline istek atan bir metodun başına aşağıdaki koyabilirsiniz.
@Cacheable(value="view", key="#model.items[0]") })
predictionio items olarak productIdler bekliyor ama genelde payload’da bir tane atıyoruz.
Yeni oldukça ekleyeceğim …
Client tarafına da değineceğim …
Sorularınızı bekliyorum.
İyi Okumalar.