Menü
Bedava
kayıt
ev  /  ÜZERİNDE/ Geri dönülmez başarı php. Basit bir PHP ve AJAX örneği

Geri dönülmez başarı php. Basit bir PHP ve AJAX örneği

Selamlar sevgili arkadaşım!

"Sizin için hayatta başarı nedir?"

Lütfen, bir düşünün, bir dakika durun.

Tamam, şimdi sana yardım etmeme izin ver. Neyin başarı olmadığı hakkında bir önceki bültende yazmıştım. Bu kavramları bir an önce terk edeceğiz.

Başarı ruhsal uyumdur.
Başarı mutlu olmaktır.
Başarı, kişinin kendini gerçekleştirmesi ve potansiyelini ortaya çıkarmasıdır.
Başarı, hayatta tatmin olmaktır.
Başarı, sizi ateşleyen sevdiğiniz şeyi yapmaktır ve bunu günün her saatinde yapabilirsiniz.
Başarı, kendini başkalarına vermek ve bu dünyayı daha iyi bir yer ve diğer insanları daha mutlu kılmaktır.
.

Başarı ayrılmaz bir şekilde zihin durumuyla bağlantılıdır. Ruhumuz bu dünyaya zevk almak ve kendini gerçekleştirmek için geldi ve biz (zihnimiz, bedenimiz, bilincimiz) onu bu konuda desteklemeliyiz. Ruhumuz kendini yarattığında ve fark ettiğinde mutlu oluyoruz. Ruhumuzun yaratılışının ve yaptıklarımızın diğer insanlara büyük fayda sağladığını hissettiğimizde ve gördüğümüzde, mutluluk duyarız. Başarı denilen şey budur. Başarı, hayatın gerçekleşmesidir.

Ruhun yeteneklerinin herhangi bir şekilde gerçekleşmesi ancak diğer insanlar sayesinde mümkündür.. Ruh kendisi için yaratmaz. Başkaları için yaratır - onlara yardım etmek ve başkalarının hayatlarını doldurmak ve onlara mutluluğunun bir parçasını vermek için. Mutlu bir insan mutluluğunun bir parçasını başkalarına, mutsuz bir insan mutsuzluğunu başkalarına aktarır. Mutsuz insanlardan kaçının!

Birdenbire tüm insanlar bir anda ortadan kaybolursa, kendini gerçekleştirme imkansız hale gelecektir - kitap yazmanın ne anlamı var, çünkü kimse okuyamayacak, yeni kıyafet modelleri yaratmanın ne anlamı var, çünkü kimse onları giymeyecek, ne kimsenin yaşamadığı yeni evler inşa etmenin amacı nedir?

Açıkçası bu mantıklı değil.

Burada kendini gösterir başarının ikili doğası: ruh kendini yaratır ve gerçekleştirir ve ayrıca diğer insanların daha mutlu olmasına yardımcı olur.
Çoğu kesin tanım Verebileceğim başarı kulağa şöyle gelebilir: başarı, kişinin dünyamızı daha iyi, daha mükemmel ve insanları daha mutlu yapan gerçek yeteneklerinin farkına varmasıdır.

bunu derinden anlamanı istiyorum sadece kendileri için yaşayan ve sadece kendileri için servet toplayan insanlar mutsuzdur. Bu zenginlikleri, anlamsız bir hayatın sonucunda oluşan manevi boşluğu doldurmak için toplarlar. Ancak bu boşluk sadece sevgiyle doldurulabilir, diğer insanlara değer katabilir. Ruh, bu dünyayı daha iyi bir yer haline getirmek için kendini aşırıya kaçmadan verdiğinde mutlu olur. Ve bir insanın öldüğünde topladığı tüm bu zenginliklerin ne anlamı var, çünkü dayanıklı değiliz. Ruh, değer yaratmaya, kendini gerçekleştirmeye gelir ve ardından "eve" döner. Bu değeri yaratmıyor, başka bir şeyle uğraşıyorsa kendini kötü hisseder. Bu dünyaya geldiğini ve istediğini yapmadığını hissediyor. Ve bunun nedeni zihnimizdir - bu kelimenin genel anlayışında "başarı" ile kördür. Aldatıcının peşinden gider ve bunu başardığında, eğer başarabilirse, elde ettiği şeyin anlamsızlığını anlar.

Genel anlamda başarı nedir?
- zenginlik (para, maddi şeyler)
- şöhret, güç, popülerlik
- durum

Ama bak hepsi egodan geliyor. Kişi önemini hissetmek ister ama zenginliğin, şöhretin, statünün bir yanılsama olduğunu anlamaz. Deniz suyu gibidirler ne kadar içersen iç susuzluğunu gideremezsin. Çünkü insanlar hayatları boyunca onların peşinden koşarlar. Bu kadar para kazanırsam ve mutlu olacağımı, yılda 100.000 dolar gelir düzeyine ulaşırsam mutlu olacağımı, sahneye çıkıp şarkı söylersem mutlu olacağımı, mutlu olacağımı düşünüyorlar. evliyim, çocuklarım olacak... Bir bakabilirsin ama %100 kesinlikle mutlu olmayacağını söyleyebilirim. Üstelik mutluluk seviyeniz daha da düşecek. Çağrınızdan uzaklaşıyorsunuz ve bunu fark edince ruh daha da mutsuz oluyor. Ne kadar çok zenginlik, şöhret, statü elde ederseniz, zihin yaşam üzerinde o kadar fazla kontrol sahibi olur ve ruhun rolü o kadar ileri düşer. Fakat gerçek mutluluk ruhtan gelir!!!

Başarı ruh ve zihin arasındaki uyumdur. Aklın rolü, Yardım Edin kendini gerçekleştirme ruhu. Yanlış yola öncelik veriyoruz. Kısa ömürlü bedeni ve maddi şeyleri ilk sıraya, ölümsüz ruhu ve tükenmez zenginlikleri en son sıraya koyduk. Mukaddes Kitap, "Zenginliği yeryüzünde değil, cennette elde edin" der. Bedenimiz ruhun aracıdır. Ruh, Yüksek Akıl ile bağlantılıdır ve sadece bu dünya için neyin gerekli olduğunu anlayabilir. Evren kendi yolunda giden insanları tercih eder. Sizin yolunuz en az enerji tüketen yoldur ve bizim dünyamızda her şey en az dirençli yoldan akar. Her zaman başarının olayların normal seyri olduğunu söylerim. Başarısızlık, normdan sapmadır. Şimdi olmasını istediğiniz kadar başarılı değilseniz, o zaman yapmak istediğiniz şeyi yapmıyorsunuz demektir. Ruh ve zihin karşı karşıyadır. Ve bu anlaşmazlık ne kadar fazlaysa, kişi o kadar mutsuz olur.

Ama insanın maddi şeylere ihtiyacı olmadığını söylediğimi düşünmüyorsunuz. Çok gerekli. Ve işte nedeni: Bir kişinin parası olmadığında, işe gitmeye ve bir tür "aptallıkla" meşgul olmaya zorlanır. İnsan günde 10 saatini para kazanmak için harcar ama bunu yaparak kendini fark etmez. Patron, sizin pahasına kendini gerçekleştiren kişidir. (Çoğu durumda bunun nasıl olduğundan bahsediyorum. Çoğu insan işlerinden nefret eder, ancak hayatta kalmak için paraya ihtiyaçları olduğu için çalışırlar).

Maddi şeyler ruh için rahatlık yaratır. Maddi şeyler bu dünyayı ruh için donatır. İlham veren mekanlarda başyapıtlar yaratmak ruhun çok daha hoşuna gider. Deniz kenarındaki bir evde resim yapmak, bir "çöp çukurundan" çok daha iyidir. Yaratmak için ruhun huzura ve rahata ihtiyacı vardır. Ama ailenin yeterli parası yoksa ve karı koca her gün bunun hakkında yemin ederse nasıl bir barış olabilir.

Ruhun kendini ifade etmesi için zamana ihtiyacı vardır. Ancak bir süre geçtikten sonra, ruhun yarattığı değer, bir insanın işyerinde kazandığından yüzlerce, hatta binlerce kat daha pahalıya satılabilir ve satılabilir. Ancak bu tür bir değeri yaratmak zaman alır. Şahsen, yetersiz bir gelire ulaşmam 5 ayımı aldı. 8 ay sonra sitem zaten fakir bir ailenin geçimini sağlayabileceği gelir elde etmeye başladı. Ve ancak 17 ay sonra sitem gelir elde etmeye başladı, bu zaten çok yüksek ücretli bir işten elde edilen gelirin yerini alacak.

İşi değiştirmek 17 ay sürdü. Ama şimdi özgürüm! Sevdiğim şeyi yapıyorum ve bu sadece başlangıç. Rüyalarım için sınır yok - ve bu nedenle benim için sınır yok. Kendi işinize baktığınız zaman, geliriniz sadece hayal gücünüzle sınırlıdır, başka bir şey değil. Kim işyerinde yılda 1.000.000 dolar kazanıyor? Evet, birimler olabilir. Ama kendi işini yapmak, bu bile bir şapel değil.
Malzeme önemlidir, ancak yalnızca yaşamın ihtiyaçlarını karşılamak için.

Dürüst olacağım: gelir olmadan şaheserler yaratmak ve yaratmak daha zordur. Zihin sürekli şöyle der: “Yaptığın şey iyi ama biz ne için yaşayacağız?”. Ve bu soru sürekli ve güçlü bir şekilde yaratıcılıktan uzaklaşıyor. Mutluluğumuzu elimizden alıyor. Bu diyaloğu kapatmak için en sevdiğiniz eğlencenin para getirmesi gerekir. Tabii ki, zihin daha sonra başka sorular sormaya başlar, ama ne daha fazla para favori bir şey getirirse, bu sorular daha az hasta ve dikkat dağıtıcı hale gelir.

Genellikle insanlar işte çalışır, para kazanır, ancak yine de hobileri vardır. hobi nedir?
Hobi, ruh için gelir getirmeyen bir uğraştır. Ama neden bir hobiyi işe çevirmiyorsunuz? En mutlu insanlar hobisi iş olanlardır. Durmadan sevdikleri işi yapıyorlar.
İş hakkında, para hakkında konuştuğum her şey, size iki önemli düşünceyi iletmek istiyorum: 1) Ruh ve zihin uyum içinde olmalıdır.
2) Maddi olmayan her zaman önce gelmelidir

Odak sadece maddi olmayan üzerinde olmalıdır! Sonuç olarak verilecek malzeme. İşte hayattaki doğru öncelikler:
mutluluk -> sağlık -> zenginlik Ve birçok insan şemaya göre yaşıyor
zenginlik->sağlık->mutluluk
Daha da kötüsü, bu plana göre yaşayan insanlar var.
servet->servet->servet

Mutlu olmamalarına şaşmamalı. Bu insanların milyonları var ama arkadaşları yok, aile sorunları var. İnsanlarla sorunları var. Çünkü etraflarındaki tüm insanların sırf paraları ve sırf paraları için yanlarında olduğunu düşünürler. Sizi bilmem ama ben böyle bir mutluluk istemezdim. Hayattaki öncelikler doğru belirlendiğinde, sonuç olarak zenginlik ortaya çıkar. Buna odaklanmanın bir anlamı yok. Yüksek düzeyde mutluluk ve sağlık, kaçınılmaz olarak yüksek gelir düzeylerine yol açar..

Maddi şeyler ve zenginliğimiz sadece mutluluğumuza ek olarak hizmet edebilir. Vakıf olarak hizmet edemezler. Temel nedir, yukarıda sizinle zaten tartıştık.

Sorguyu özelleştiren bir dizi anahtar/değer çifti AJAX. Tüm parametreler isteğe bağlıdır. $.ajaxSetup() yöntemini kullanarak herhangi bir parametre için varsayılan bir değer ayarlanmasına izin verilir, ancak önerilmez.
Yöntem $.ajax() aşağıdaki seçenekleri destekler:

    kabul eder(varsayılan: bağlıdır veri tipi).

    Tür: PlainObject .
    Gönderilen anahtar/değer çiftleri kümesi Kabul istek başlığı Bu başlık sunucuya isteğin karşılığında ne tür bir yanıt alacağını söyler. Belirtilen parametrenin değerinin veri tipi(sunucudan beklediğimiz veri türü) parametrede belirtilenle eşleştirilir. Ek olarak, sunucudan gelen yanıtın doğru işlenmesi için parametrede gereklidir. dönüştürücüler dönüştürülen yanıt değerini döndüren bir işlev belirtin. Örneğin: $.ajax(( kabul eder: (özel tipim: " application/x-bazı-özel tip" } , // yanıtın nasıl işleneceğini belirtin dönüştürücüler: ( "metin benim özel tipim ": işlev ( sonuç) { // dönüştürülen yanıt değerini döndür yeni sonuç döndür; ) ), // Beklenen veri türü ("mycustomtype") veri tipi: "özel tipim" ) );

    zaman uyumsuz(varsayılan: true ).

    Tür: Boole .
    Varsayılan olarak, tüm istekler eşzamansız olarak gönderilir, eşzamanlı istekleri düzenlemeniz gerekiyorsa bu parametreyi false olarak ayarlayın. Lütfen etki alanları arası isteklerin ve öğenin, parametrenin veri tipi hangisi önemli jsonp eşzamanlı modda istekleri desteklemeyin. Eşzamanlı istekleri kullanarak, istek etkinken herhangi bir eylemi devre dışı bırakarak tarayıcıyı geçici olarak engelleyebileceğinizi unutmayın.

    önceGönder. Tür: İşlev(jqXHR jqXHR, DüzNesne ayarlar).
    AJAX isteği yapılmadan önce çağrılacak bir geri arama işlevi. İşlev, jqXHR nesnesini (jQuery 1.4.x'te XMLHTTPRequest nesnesini) gönderilmeden önce değiştirmenize olanak tanır. jqXHR nesnesi, XMLHttpRequest nesnesini genişleten bir eklentidir, nesne, daha fazlasını elde etmenizi sağlayan birçok özellik ve yöntem içerir. full bilgi sunucu yanıtı hakkında, nesnenin yanı sıra Promise yöntemlerini içerir. eğer fonksiyon önceGönder false döndürür, ardından AJAX isteği iptal edilir. sürümden başlayarak jQuery 1.5 işlev önceGönder istek türünden bağımsız olarak çağrılır.

    önbellek(varsayılan: true , için veri tipi "senaryo" ve jsonp YANLIŞ ).

    Tür: Boole .
    false olarak ayarlanırsa, bu istenen sayfaların tarayıcı tarafından önbelleğe alınmamasını sağlar. false öğesinin yalnızca doğru şekilde çalışacağını unutmayın. KAFA ve ALMAK istekler.

    tamamlayınız.

    Tür: İşlev(jqXHR jqXHR, Sicim metinDurumu).
    İstek sona erdiğinde çağrılan bir işlev (işlev AJAX olaylarından sonra yürütülür) "başarı" veya "hata"). İşleve iki parametre iletilir: jqXHR(jQuery 1.4.x nesnesinde XMLHTTPTalebi) ve isteğin durumuna karşılık gelen bir dize ( "başarı", "modifiye edilmemiş", "içerik yok", "hata", "zaman aşımı", "kürtaj", veya "ayrıştırıcı hata"). jQuery 1.5 ile başlayarak, parametre tamamlayınız sırayla çağrılacak bir dizi işlevi alabilir.

    içindekiler.

    Tür: PlainObject .
    İçerik türüne bağlı olarak jQuery'nin yanıtı nasıl işleyeceğini (çözümleyeceğini) tanımlayan dize/regex çiftlerinden oluşan bir nesne. jQuery 1.5'e eklendi.

    içerik türü(varsayılan: "application/x-www-form-urlencoded; karakter kümesi=UTF-8").

    Tür: Boolean veya String .
    Sunucuya veri aktarılırken istekte belirtilen içerik türünü belirtir. jQuery 1.6'dan itibaren false değerini belirtmeye izin verilir, bu durumda jQuery başlıktaki alanı geçmez İçerik türü hiç.

    bağlam.

    Tür: PlainObject .
    AJAX geri çağırma işlevlerini yürütürken, yürütme bağlamları pencere nesnesidir. Parametre bağlam$(this ) belirli bir DOM öğesine veya nesneye başvuracak şekilde bir işlevin yürütme bağlamını ayarlamanıza olanak tanır. Örneğin: $.ajax(( url: "test.html" bağlam: $(".benimSınıfım"), // yeni fonksiyon yürütme bağlamı başarı:işlev()( // istek başarılı olursa işlevi çağırın$(bu ).html("Her şey yolunda"); // class.myClass ile öğeye metin içeriği ekle } } );

    dönüştürücüler

    Varsayılan değerler:
    ("* metin ": pencere.Dize, // metne herhangi bir tür"metin html ": true , // metinden html'ye "metin json ": jQuery.parseJSON, // metinden JSON'a "metin xml ": jQuery.parseXML // metinden XML'e ) Tip: PlainObject .
    Dönüştürülecek veri türünü ve nasıl dönüştürüleceğini içeren bir nesne. Her dönüştürücünün değeri, dönüştürülen yanıt değerini döndüren bir işlevdir. jQuery 1.5'e eklendi.

    etki alanları arası(varsayılan: aynı etki alanındaki istekler için yanlış, etki alanları arası istekler için doğru).

    Tür: Boole .
    Aynı etki alanındayken etki alanları arası istekte bulunmak istiyorsanız (örneğin, bir jsonp isteği), bu parametreyi true olarak ayarlayın. Bu, örneğin, bir isteği sunucunuzdan başka bir etki alanına yönlendirmenize olanak tanır. jQuery 1.5'e eklendi.

    Tür: PlainObject veya String veya Array.
    Sunucuya gönderilecek veriler. Bir dize değilse, bir sorgu dizesine dönüştürülürler. İçin ALMAK URL'ye istekler dizesi eklenecektir. Otomatik işlemeyi önlemek için parametreyi kullanabilirsiniz. Veri işleme false değeri ile. Veri bir nesnenin parçası olarak iletilirse, anahtar/değer çiftlerinden oluşmalıdır. Değer bir dizi ise, jQuery aynı anahtarla (parametrenin değerine bağlı olarak) birden çok değeri seri hale getirecektir. geleneksel, $.param yöntemine dayalı geleneksel serileştirme türünü kullanmanıza izin verir).

    veri filtresi.

    Tür: İşlev(Dize veri, Sicim tip) => Herhangi bir şey .
    İşlev, başarılı bir AJAX isteğinden sonra çağrılır ve sunucu yanıtından alınan "ham" verileri işlemenize olanak tanır. Veriler işlendikten hemen sonra iade edilmelidir. İşlev iki argüman alır: veri- sunucudan bir dizi olarak alınan veriler ve tip- bu verinin türü (parametre değeri veri tipi).

    veri tipi(varsayılan: xml, json, senaryo, veya html).

    Tür: Dize .
    Sunucudan almayı beklediğiniz veri türünü belirtir. Veri türü belirtilmemişse, jQuery bunu yanıttaki MIME türüne göre belirlemeye çalışır ( XML bir tür MIME jQuery 1.4'ten itibaren XML ile sonuçlanacak json bir nesne verecek JavaScript, senaryo betiği çalıştıracak ve diğer her şey bir dize olarak döndürülecek).

    Temel türler (sonuç, geri arama işlevine ilk argüman olarak iletilir başarı):

    • "xml"- İadeler XML jQuery ile işlenebilen bir belge.
    • "html"- İadeler HTML düz metin, etiketler gibi

      ile çalışmanın en kolay yolu AJAXçerçeveyi bağlamaktır jQuery bu tam olarak yaptığım şey. jQuery bize göndermek için anlaşılması ve çalışması kolay bir sözdizimi sağlar AJAX istekler, neden bundan faydalanmıyorsunuz?

      js betiği oluşturma

      validate.js dosyası sözdizimi

      $(document).ready(function()( var email = ""; $("#email").keyup(function()( var value = $(bu).val(); $.ajax(( tür: "POST", url:"email.php", data:"email="+değer, başarı:function(msg)( if(msg == "geçerli")( $("#message").html(" Bu e-posta kullanılabilir.Bu e-posta zaten alınmış."); ) ) )); )); $("#submit").click(function()( if(email == "")( alert("Lütfen tüm e-postalara veri koyun"); )else( $.ajax(( type: "POST", url:"email.php", data:"add_email="+email, Success:function(msg)( $("#message").html(msg); ) ) ); ) )); ));

      php işleyicisi

      Bu komut dosyası alacak İLETİİstemciden istekte bulunun, işleyin ve sonucu döndürün. AJAX sonucu okur ve ona göre karar verir.
      email.php dosyasının sözdizimi

      $bağlantı = mysqli_connect("localhost","email","email","email"); if(isset($_POST["email"]) && $_POST["email"] != "")( $email = $_POST["email"]; $email = mysqli_real_escape_string($bağlantı,$email); if (!filter_var($email, FILTER_VALIDATE_EMAIL))( echo "invalid"; )else( $sql = "SELECT id FROM email WHERE email="$email""; $result = mysqli_query($connection,$sql); if( mysqli_num_rows($result) == 1)( echo "geçersiz"; )else( echo "geçerli"; ) ) ) if(isset($_POST["add_email"]) && $_POST["add_email"] != "" )( $email = mysqli_real_escape_string($connection,$_POST["add_email"]); $sql = "E-postaya GİRİN(email) VALUES("$email")"; if(mysqli_query($bağlantı,$sql))( Eko Başarı"; )else( yankı " hata"; } }

      PHP betiğimizde, gönderi isteğini işleyen ve sayfadaki belirli metni yazdıran en yaygın kod. Sonuç olarak AJAX bir istek gönderir php betiği, komut dosyası onu işler ve sonucu verir, AJAX sonucu okur ve sayfayı gerçek zamanlı olarak değiştirir.

      AJAX, POST isteğini bu kod parçasıyla komut dosyasına iletir:

      $.ajax(( type:"POST", url:"email.php", data:"email="+value, Success:function(msg)( if(msg == "geçerli")( $("#message)" ").html(" Bu e-posta kullanılabilir."); email = değer; )else( $("#message").html(" Bu e-posta zaten alınmış."); } } });

      tür - İstek türü, POST veya GET. Bizim durumumuzda POST;
      url - isteğin gönderildiği komut dosyasının adresi;
      veri - istekte iletilen veriler;
      başarı - başarılı bir istek sonucunda ne yapılmalı. Bizim durumumuzda bir fonksiyon çağrılır;

      Komut dosyasının kendisinde, e-posta alanına her karakter girildiğinde, veritabanında e-posta olup olmadığının kontrol edilmesi gerçekleştirilir. Komut dosyasında, girdinin işlenmesinden $("#email").keyup(function()()); bölümü sorumludur. id = "email" olan alanda bir tuşa basıp basmadığını kontrol eden .
      Gördüğünüz gibi, kod oldukça basittir ve anlamak için özellikle büyük beceriler gerektirmez, her şey keyup () olaylarının işlenmesine bağlıdır - bir tuşa basın, tıklayın () - bir öğe üzerinde fareyi tıklayın. Bunu takiben AJAX komut dosyasından istek ve yanıt. Böylece, php ve ajax kullanarak etkileşimli sayfalar oluşturmak için neredeyse sınırsız olanaklar elde edebilirsiniz.
      Bu kod çok kaliteli gibi durmuyor ama geliştirip client ve server seviyelerinde doğru validasyonları ekleyip css girdiğinizde projelerinizde kullanabilirsiniz.
      Herhangi bir sorunuz varsa, yorum yazmaktan çekinmeyin.
      İyi günler dilerim, görüşmek üzere 🙂

      Vize: Blaue Karte AB

      Belgelerin sunulması sırasında 29 yıl

      Astrakhan'dan

      Büyükelçilik şehri: Moskova

      Üniversite, uzmanlık: Astrakhan Devlet Teknik Üniversitesi, Entegre destek bilgi Güvenliği otomatik sistemler

      Diller: İngilizce orta

      Hepsi nasıl başladı:

      Bir yere taşınma arzusu uzun zamandır oradaydı. Doğru, esas olarak, denizi olan sıcak ülkeler kabul edildi. Karadağ veya Bulgaristan'a taşınmak için toprağı iki kez ciddi bir şekilde araştırdılar. Sonuç olarak, son anda, şu veya bu nedenle fikirlerini değiştirdiler. Arabanın satışı için yapılan ciddi hazırlıkların ardından son kez Eylül 2014'te.

      Ekim ayında, yanlışlıkla Almanya'ya yerleşen programcıların aranmasıyla ilgili bir duyuru gördüm. O zamanlar Mavi Kartın varlığından haberim yoktu ve Almanya'yı AB üyesi olmayan vatandaşlara karşı inanılmaz derecede katı bir göç politikası olan bir ülke olarak görüyordum.

      Bir dereceye kadar şüphe ve güvensizlikle Skype'ta yazdım. Ekranın diğer tarafında, BT personelinin seçiminde ve ardından Almanya'ya taşınmasıyla ilgilenen bir işe alım görevlisi kız (Alina) yanıtladı. İlk iletişimimiz sırasında, merkezi Berlin'de bulunan büyük bir çevrimiçi mağaza için programcılar işe alındı. Özgeçmişimi gönderdim ve bekledim.

      Bir süre sonra Alina, Almanya'dan gelen meslektaşının dil seviyesini ve yeterliliğini değerlendirmek için benimle konuşacağını söyledi. Görüşme - sadece iki mantıksal bulmaca içeren bir konuşma, Skype'ta 30 dakika sürdü. Sonra beklemem söylendi. Yaklaşık bir hafta sonra, ilk teknik görüşme planlandı. Teknik görüşme ayrıca şirketin geliştiricilerinden biriyle Skype'ta yapıldı. Bence gayet iyi geçti ama bir hafta sonra bana uymadığımı söylediler. Bu arada, belirli nedenlerle Alina'dan tek bir aday geçmedi.

      Her şey nasıl ortaya çıktı:

      Biraz üzgün ama hayat devam ediyor. Ve birkaç gün sonra Alina, Stuttgart'tan geliştirici arayan yeni bir müşterileri olduğunu ve benim için bir röportaj planlandığını söyledi. Röportajın ilk bölümü BT ve İK departmanlarının başkanı ile paylaşılır. Deneyim, kendim ve şirket hakkında genel sohbet, her iki taraftan da bol kahkaha ve şakalar. Görünüşe göre mizah tarzım benim hoşuma gidiyordu, bu yüzden birkaç gün sonra potansiyel bir doğrudan süpervizörle teknik bir röportaj için görevlendirildim. Röportajın bu kısmı beni biraz şaşırttı, çünkü adaylardan birinin daha sonra söylediği gibi, "iki programcı arasında bir bardak bira içerek geçen bir konuşma" gibi görünüyordu. Aynı günün akşamı ofiste kişisel bir görüşme için davet aldım.

      O zaman açık bir Schengen vizem yoktu. Gerekli belgeler acilen toplandı. Moskova'daki Alman vize merkezine başvurdum. acil vize ve hemen ertesi gün pasaportumu vize ile aldım. için müracaat ettim davetiye ile ticari vize Bana Esslingen'den gönderilen , iletişim kurmaya davet edildiğim ve şirketin uçuşlar, transferler, yemekler ve konaklama ile ilgili tüm finansal konularla ilgilendiğinin açıkça belirtildiği bir mektuptur.

      Ofisteki kişisel iletişim, şirketin üç ana BT başkanı ile gerçekleşti. İlk bölüm yine sadece deneyim, beceriler ve bazı konularda genel bir anlayış hakkında bir konuşmadır. İkincisi bilgisayar başında. Dürüst olmak gerekirse, “test tecrübesi olan genç” seviyesinin çok, çok kolay görevleri :). Görevler yapıldı. Bundan sonra, öğle yemeği ve hemen iki nüsha iş sözleşmesi şeklinde bir teklif (pozisyon Kıdemli PHP Geliştiricisi) şirket tarafından imzalanmıştır. Biraz düşündüm ve bir hafta içinde cevap vereceğimi söyledim.

      Karar verildi ve vize başvurusu için hazırlanmaya başladım.

      Nasıl taşındık:

      Şirket benim ve ailem (2,5 yaşındaki eşim ve kızım) için uçuş ücretini ödedi, ilk üç ay bizim için bir daire kiraladı (benim durumumda, deniz manzaralı ideal bir yer). merkez meydan Marktplatz) ve ilk kez yardım etmesi için bir kişi tahsis etti. Bu bir yer değiştirme acentesi değil saf formu, ancak ortaya çıkan tüm soruları onun aracılığıyla çözdük. Şirketteki ilk AB üyesi olmayan çalışan bendim, o kadar çok soru vardı ki üzerimde. Şimdi, bana ek olarak, şirkette Kiev'den başka bir adam çalışıyor (benden bir ay sonra geldi) ve Odessa'dan bir geliştirici taşınmaya hazırlanıyor. Hepsi de Alina'nın yardımı olmadan işe alındı.

      Burada istihdam sürecinde tüm sorularımı çözen Alina'ya çok minnettar olduğumu belirtmek isterim. İstihdamın ve sonraki adaptasyonun tüm aşamalarında yardım etmeye ve gerekli sorunu çözmeye hazır bir kişi olduğu için çok şanslıydım.

      İlk başta yalnız uçtum, iki hafta sonra ailem geldi. Varışta, kimse bir araya gelmiyor, bir otelde yaşadığım ilk birkaç gün dairemin boş olmasını bekliyorum. Otelden alındım ve mekana getirildim 🙂

      Şeylerden gerekli minimumları aldı.

      ABH ile her şey çok hızlı gitti. Tüm bu sorunlar, şirketin bir çalışanı ile ortaklaşa çözüldü. ABH geldikten sonra oldukça erken bir dönem atadı, başvurduk ve üç hafta içinde eAT kartlarımızı aldık.

      Nasıl kurduk:

      Üzerinde şu an Stuttgart'tan sadece 15 dakika uzaklıkta bulunan, inanılmaz derecede güzel ve temiz bir kasaba olan Esslingen'de yaşıyoruz. Henüz dil bilmememizden dolayı herhangi bir rahatsızlık hissetmiyoruz, çoğu durumda kendimizi İngilizce olarak veya aşırı durumlarda jestlerle açıklamak mümkün. Şu anda var olan tek sorun daire kiralamak. Çok az teklif var ve talep inanılmaz derecede yüksek. Stuttgart'taki konut durumu biraz daha kolay ama ben Esslingen'de kalmak istiyorum.

      Yaklaşık tarihlerle kısa özet:

      Ekim ortası 2014- Programcı aramayla ilgili bir reklam gördüm

      Ekim sonu - Kasım ortası - ilk şirketle yapılan görüşmeler

      Kasım Ortası - Kasım Sonu - Mevcut şirketimle mülakatlar, kişisel mülakat için teklif alma

      20 Ocak - 1 Şubat 2015 g.- ulusal vize başvurusu, vizeli pasaport alınması

      ). Bulut, bir programda veya bir API aracılığıyla çeşitli PHP komut dosyalarını çalıştırmak için tasarlanmıştır. Tipik olarak, bu komut dosyaları kuyrukları işler ve yük yaklaşık 100 sunucuya "yayılır". Daha önce, yükü bu kadar çok sayıda sunucuya eşit olarak dağıtmaktan ve bir programa göre görevler oluşturmaktan sorumlu olan kontrol mantığının nasıl uygulandığına odaklanmıştık. Ancak bunun yanı sıra, PHP betiklerimizi CLI'de çalıştırabilecek ve yürütme durumlarını izleyebilecek bir arka plan programı yazmamız gerekiyordu.

      Şirketimizdeki diğer tüm iblisler gibi başlangıçta C ile yazılmıştır. Bununla birlikte, işlemci zamanının önemli bir bölümünün (yaklaşık %10) aslında boşuna harcandığı gerçeğiyle karşı karşıya kaldık: bu, yorumlayıcının başlatılması ve çerçevemizin “çekirdeğinin” yüklenmesidir. Bu nedenle, yorumlayıcıyı ve çerçevemizi yalnızca bir kez başlatabilmek için arka plan programının PHP'de yeniden yazılmasına karar verildi. Biz buna PHP adını verdik kaynak syd (Phproxyd - PHP Proxy Daemon'a benzer, daha önce sahip olduğumuz C arka plan programı). Bireysel sınıfları çalıştırma isteklerini kabul eder ve her istek için bir çatal() yapar ve ayrıca her bir başlatmanın yürütme durumunu nasıl rapor edeceğini bilir. Bu mimari birçok yönden Apache web sunucusu modeline benzer, tüm başlatmalar "ana"da bir kez yapıldığında ve "çocuklar" zaten isteği işlerken. Ek bir avantaj olarak, tüm çocuklar ana işlemle aynı paylaşılan bellek alanını devraldığı için düzgün çalışacak olan CLI'de işlem kodu önbelleğini etkinleştirme olanağına sahibiz. Bir başlatma isteğini işlerken gecikmeleri azaltmak için önceden fork() yapabilirsiniz (prefork modeli), ancak bizim durumumuzda fork() gecikmeleri yaklaşık 1 ms'dir ve bu bize mükemmel şekilde uyar.

      Ancak, kodu oldukça sık güncellediğimiz için, bu arka plan programının da sık sık yeniden başlatılması gerekiyor, aksi takdirde içine yüklenen kod güncelliğini yitirebilir. Her yeniden başlatma gibi birçok hata eşlik edeceğinden eş tarafından bağlantı sıfırlama son kullanıcılar için hizmet reddi de dahil olmak üzere (arka plan programı yalnızca bulut için değil, aynı zamanda sitemizin bir kısmı için de yararlıdır), arka plan programını kaybetmeden yeniden başlatmanın yollarını aramaya karar verdik kurulan bağlantılar. yapmak için kullanılan popüler bir teknik vardır. zarif yeniden yükleme arka plan programları için: fork-exec yapılır ve dinleme soketindeki tanımlayıcı çocuğa iletilir. Yani yeni bağlantılar zaten kabul edildi Yeni sürüm arka plan programı ve eskileri eski sürüm kullanılarak "tamamlandı".

      Bu yazıda, daha karmaşık bir versiyonu ele alacağız. zarif yeniden yükleme: eski bağlantılar, bizim durumumuzda önemli olan arka plan programının yeni sürümü tarafından işlenmeye devam edecek, aksi takdirde eski kodu çalıştıracaktır.

      teori

      Önce bir düşünelim: elde etmek istediğimiz şey mümkün mü? Ve eğer öyleyse, bu nasıl başarılabilir?

      Daemon, POSIX uyumlu Linux altında çalıştığından, aşağıdaki seçenekler bizim için kullanılabilir:

      1. Tüm açık dosyalar ve soketler, açık tanımlayıcı numarasına karşılık gelen sayılardır. Standart girdi, çıktı ve hata akışı sırasıyla 0, 1 ve 2 tanımlayıcılarına sahiptir.
      2. Arasında önemli bir fark yok açık dosya, bir soket ve bir boru (boru) mevcut değil (örneğin, hem read/write hem de sendto/recvfrom sistem çağrılarını kullanarak soketlerle çalışabilirsiniz).
      3. fork() sistem çağrısı yürütüldüğünde, tüm açık tanımlayıcılar, sayıları ve okuma/yazma konumları (dosyalarda) korunarak devralınır.
      4. execve() sistem çağrısı yürütüldüğünde, tüm açık tutamaçlar da miras alınır ve buna ek olarak, Proses PID'si ve dolayısıyla çocuklarıyla bağ kurarlar.
      5. Açık işlem tanıtıcılarının listesi, Linux'ta /proc/self/fd'ye bir sembolik bağlantı olan /dev/fd dizininde bulunur.
      Bu nedenle, görevimizin çok fazla çaba harcamadan gerçekleştirilebilir olduğuna inanmak için her türlü nedenimiz var. O halde başlayalım.

      PHP yamaları

      Ne yazık ki, işimizi zorlaştıran küçük bir ayrıntı var: PHP'de akışlar (akışlar) için dosya tanıtıcı numarasını almanın ve dosya tanıtıcıyı numaraya göre açmanın bir yolu yoktur (bunun yerine dosya tanıtıcısının bir kopyası açılır; bizim arka plan programımız için uygun değil, çünkü çok dikkatli olduğumuz için açık tanımlayıcıları yeniden başlatırken ve alt süreçleri başlatırken sızıntı oluşturmamak için dikkatle izliyoruz).

      İlk olarak, akıştan (akım) fd alma yeteneğini eklemek için PHP koduna birkaç küçük yama yapacağız ve onu fopen(php://fd/ ) tanıtıcının bir kopyasını açmadı (ikinci değişiklik mevcut PHP davranışıyla uyumlu değil, bu nedenle bunun yerine yeni bir "adres" eklenebilir, örneğin php://fdraw/ ):

      yama kodu

      diff --git a/ext/standard/php_fopen_wrapper.cb/ext/standard/php_fopen_wrapper.c indeksi f8d7bda..fee964c 100644 --- a/ext/standard/php_fopen_wrapper.c +++ b/ext/standard/php_fopen_wrapper. c @@ -24,6 +24.7 @@ #if HAVE_UNISTD_H #include #endif +#include #include "php.h" #include "php_globals.h" @@ -296.11 +297.11 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, char *path, ch "Dosya tanımlayıcıları, %d'den küçük negatif olmayan sayılar olmalıdır" , dtablesize); NULL döndür; ) - - fd = dup(fildes_ori); - if (fd == -1) ( + + fd = fildes_ori; + if (fcntl(fildes_ori, F_GETFD) == -1) ( php_stream_wrapper_log_error(wrapper, seçenekler TSRMLS_CC, - "Dosya tanıtıcısı %ld kopyalanırken hata oluştu; muhtemelen çalışmıyor 't "t mevcut: " + "Dosya tanımlayıcı %ld geçersiz: " "[%d]: %s", fildes_ori, errno, strerror(errno)); return NULL; ) diff --git a/ext/standard/ streamsfuncs.cb/ext/standard/streamsfuncs.c dizin 0610ecf..14fd3b0 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -24,6 +24.7 @ @ # "ext/standard/flock_compat.h" dahil #include "ext/standard/file.h" #include "ext/standard/php_filestat.h" +#include "ext/standard/php_fopen_wrappers.h" #include "php_open_temporary_file .h " #include "ext/standard/basic_functions.h" #include "php_ini.h" @@ -484.6 +485.7 @@ PHP_FUNCTION(stream_get_meta_data) zval *arg1; php_stream *stream; zval *newval; + int tmp_fd; if (zend_parse_parameters) (ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == BAŞARISIZ) ( dönüş; @@ -502.6 +504.9 @@ PHP_FUNCTION(stream_get_m eta_data) add_assoc_string(return_value, "wrapper_type", (char *)stream->wrapper->wops->label, 1); ) add_assoc_string(return_value, "stream_type", (char *)stream->ops->label, 1); + if (BAŞARI == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&tmp_fd, 1) && tmp_fd != -1) ( + add_assoc_long(dönüş_değeri, "fd", t_mp_fd); ", akış->mod, 1);


      Eğer mantıklıysa, fd alanını stream_get_meta_data() tarafından döndürülen sonuca ekledik (örneğin, zlib akışları için fd alanı mevcut olmayacaktır). Ayrıca, geçirilen dosya tanıtıcıdaki dup() çağrısını basit bir kontrolle değiştirdik. Ne yazık ki, fcntl() çağrısı POSIX'e özgü olduğundan, bu kod Windows'ta değişiklik yapılmadan çalışmayacaktır, bu nedenle tam bir yama diğer işletim sistemleri için ek kod dalları içermelidir.

      Daemon yeniden başlatılamaz

      Başlangıç ​​olarak, istekleri JSON formatında kabul edebilecek ve bir tür yanıt verebilecek küçük bir sunucu yazacağız. Örneğin, istekte gelen dizideki öğelerin sayısını verecektir.

      Arka plan programı 31337 numaralı bağlantı noktasını dinliyor. Çıktı şöyle görünmelidir:

      $ telnet localhost 31337 127.0.0.1 deneniyor... localhost'a bağlandı. Kaçış karakteri "^]". ("hash":1) # kullanıcı girişi "İstek 1 tuşa sahipti" ("hash":1,"cnt":2) # kullanıcı girişi "İstek 2 tuşa sahipti"

      Bir portu dinlemeye başlamak için stream_socket_server()'ı ve hangi tanımlayıcıların okunmaya/yazılmaya hazır olduğunu belirlemek için stream_select()'i kullanacağız.

      Basit uygulama kodu (Simple.php)

      akış) */ özel $akışlar = ; /** @var string (client_id => okuma arabelleği) */ private $read_buf = ; /** @var string (client_id => yazma arabelleği) */ private $write_buf = ; /** @var kaynağı (client_id => okunacak akış) */ private $read = ; /** @var resource (client_id => akış nereye yazılacak) */ private $write = ; /** @var int Toplam bağlantı sayısı */ private $conn_count = 0; public function run() ( $this->listen(); echo "Ana döngüye giriliyor\n"; $this->mainLoop(); ) korumalı işlev listen() ( $port = self::PORT; $ip_port = " 0.0.0.0:$port"; $address = "tcp://$ip_port"; $server = stream_socket_server($address, $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN); if (!$sunucu) ( fwrite(STDERR, "stream_socket_server başarısız oldu: $errno $errstr\n"); çıkış(1); ) $this->read = $sunucu; echo "$address'te dinleme\n"; ) public function response($stream_id, $yanıt) ( $json_resp = json_encode($response); echo "stream$stream_id ". $json_resp. "\n"; $this->write($stream_id, $json_resp. "\n"); ) public function write($stream_id, $buf) ( $this->write_buf[$stream_id] .= $buf; if (!isset($this->write[$stream_id])) ( $this->write[$stream_id] = $this->streams [$stream_id]; ) ) public function accept($server) ( echo "Yeni bağlantı kabul ediliyor\n"; $client = stream_socket_accept($sunucu, 1, $peername); $stream_id = ($this->conn_count+ +); if (!$client) ( fwrite(STDERR, "Kabul başarısız\n"); dönüş; ) stream_set_read_buffer($client, 0); stream_set_write_buffer($istemci, 0); stream_set_blocking($istemci, 0); stream_set_timeout($istemci, 1); $this->read_buf[$stream_id] = ""; $this->write_buf[$stream_id] = ""; $this->read[$stream_id] = $this->streams[$stream_id] = $istemci; echo "Bağlı akış$stream_id: $eşadı\n"; ) özel işlev bağlantı kesme($stream_id) ( echo "stream$stream_id bağlantısını kes\n"; unset($this->read_buf[$stream_id], $this->write_buf[$stream_id]); unset($this->streams[ $stream_id]); unset($this->write[$stream_id], $this->read[$stream_id]); ) özel işlev handleRead($stream_id) ( $buf = fread($this->streams[$stream_id) ], 8192); if ($tampon === false || $buf === "") ( echo "EOF'yi stream$stream_id\n'den aldı"; if (empty($this->write_buf[$stream_id]) ) ( $this->disconnect($stream_id); ) else ( unset($this->read[$stream_id]); ) return; ) $this->read_buf[$stream_id] .= $buf; $this-> processJSONRequests($stream_id); ) özel işlev processJSONRequests($stream_id) ( if (!strpos($this->read_buf[$stream_id], "\n")) return; $requests = patlat("\n", $this ->read_buf[$stream_id]); $this->read_buf[$stream_id] = array_pop($requests); foreach ($req olarak $requests) ( $res = json_decode(rtrim($req), true); if ( $res! == false) ( $this->response($stream_id, "İstekte " .count($res) . "keys"); ) else ( $this->response($stream_id, "Invalid JSON"); ) ) ) özel işlev handleWrite($stream_id) ( if (!isset($this->write_buf[$stream_id])) ( dönüş; ) $write = fwrite($this->streams[$stream_id], substr($this-> write_buf[$stream_id], 0, 65536); if ($write === false) ( fwrite(STDERR, "#$stream_id akışına yazma başarısız\n"); $this->disconnect($stream_id); return ; ) if ($write === strlen($this->write_buf[$stream_id])) ( $this->write_buf[$stream_id] = ""; unset($this->write[$stream_id]); if (empty($this->read[$stream_id])) ( $this->disconnect($stream_id); ) ) else ( $this->write_buf[$stream_id] = substr($this->write_buf[$stream_id] , $write); ) ) public function mainLoop() ( while (true) ( ​​$read = $this->read; $write = $this->write; $except = null; echo "Selecting for " .count . ($ okuma) . " okur, " .count($yaz) . " yazar\n"; $n = stream_select($okuma, $yazma, $hariç, BOŞ); if (!$n) ( fwrite(STDERR, "stream_select()\n"); ) if (count($read)) ( echo " .count($read) . " streams\n" ; ) if (count($write)) ( echo " . count($write) . " öğesine yazabilir. " streams\n"; ) if (isset($read)) ( $this->accept($read); unset($read); ) foreach ($read as $stream_id => $_) ( $this->handleRead($stream_id); ) foreach ($write as $stream_id => $_) ( $this->handleWrite( $stream_id); ) ) ) ) $örnek = new Simple(); $örnek->çalıştır();


      Bu arka plan programının kodu standarttan daha fazlasıdır, ancak bir uygulama ayrıntısına dikkat çekmek isterim: tüm okuma ve yazma arabelleklerini belirli bağlantılara referansla saklarız ve istek işlemeyi doğrudan isteği okuduğumuz yerde gerçekleştiririz. Bu önemlidir, çünkü bu isteklerden biri yeniden başlatılabilir ve bu durumda sonraki istekler işlenmez. Ancak, istekleri henüz okumadığımız için, aynı tanımlayıcılardan gelen stream_select() bir sonraki sefer aynı sonucu döndürecektir. Böylece, doğrudan komut işleyicisinden yeniden başlatırsak tek bir isteği kaybetmeyeceğiz (aynı bağlantıda bize aynı anda birkaç komutun gönderilmesi ve bu komutlardan birinin yeniden başlatılması dışında).

      Peki, arka plan programını yeniden başlatmayı nasıl mümkün kılarsınız?

      Yeniden başlatma ve kurulan bağlantıları kaydetme ile Daemon

      En basit örneğimiz işe yarar bir şey yapamadı, o yüzden en başta bahsettiğimiz arka plan programını yazalım. Aşağıdakine benzer bir şey elde etmek istiyoruz (komutlar arka plan programına "command_name[ JSON data]" biçiminde gönderilir, yanıt JSON biçimindedir):
      $ telnet localhost 31337 127.0.0.1 deneniyor... localhost'a bağlandı. Kaçış karakteri "^]". # hemen arka plan programından yeniden başlatmasını isteyin # yanıt zaten yeniden başlatılan arka plan programı tarafından gönderilir "Başarılı bir şekilde yeniden başlatıldı" # test sınıfı çalıştırmayı çalıştırın ("hash":1,"params":,"class":"TestClass1") # run başarıyla ("error_text": "Tamam") # arka plan programını yeniden başlat (alt TestClass1 hala çalışıyor) yeniden başlat "Başarıyla yeniden başlatıldı" # görev durumunu kontrol et: hala çalışıyor kontrol ("hash":1) ("error_text":" Hala çalışıyor") # 5 saniye bekleyin ve tekrar kontrol edin: Class TestClass1 başarıyla tamamlandı kontrol ("hash":1) ("retcode":0) # arka plan programı tüm çalıştırmaları hatırlar, bu nedenle ücretsiz bir kontrol yapmanız gerekir ("hash" :1) ("retcode": 0) ücretsiz ("hash":1) ("error_text":"Tamam") yeniden başlat "Başarıyla yeniden başlatıldı" # Kodu güncelledim, böylece ikinci kez yeniden başlatmayı yeniden başlatmak için farklı bir yanıt görüyoruz ("error_text":"Başarıyla yeniden başlatıldı") hoşçakal Bağlantı yabancı ana bilgisayar tarafından kapatıldı.

      Yeniden başlatma fikri basittir: gerekli tüm bilgileri içeren bir dosya oluşturacağız ve başlangıçta onu okumaya ve açık dosya tanımlayıcılarını geri yüklemeye çalışacağız.

      Öncelikle restart dosyasına yazılacak kodu yazalım:

      echo "Yeniden başlatma dosyası oluşturuluyor...\n"; if (!$res = $this->getFdRestartData()) ( fwrite(STDERR, "FD verisi yeniden başlatılamadı, çıkılıyor, zarif yeniden başlatma desteklenmiyor\n"); exit(0); ) /* Tüm fazlalıkları kapat opendir() tanımlayıcı dahil, bilmediğimiz dosya tanımlayıcıları:) */ $dh = opendir("/proc/self/fd"); $fds = ; while (false !== ($file = readdir($dh))) ( if ($file === ".") devamı; $fds = $dosya; ) foreach ($fds as $fd) ( if (! isset($this->known_fds[$fd])) ( fclose(fopen("php://fd/" . $fd, "r+")); ) ) $içerik = serialize($res); if (file_put_contents(self::RESTART_DIR . self::RESTART_FILENAME, $contents) !== strlen($contents)) ( fwrite(STDERR, "Yeniden başlatma dosyası tam olarak yazılamadı\n"); unlink(self::RESTART_DIR . self::RESTART_FILENAME); )

      Veri dizisini (getFdRestartData() işlevi) alma kodu aşağıda gösterilmiştir:

      $res = ; foreach (self::$restart_fd_resources as $prop) ( $res[$prop] = ; foreach ($this->$prop as $k => $v) ( $meta = stream_get_meta_data($v); if (!isset ($meta["fd"])) ( fwrite(STDERR, "$v kaynağı için akış meta verisinde fd yok ($prop'da $k anahtarı), " . var_export($meta, true) . "\n") ; return false; ) $res[$prop][$k] = $meta["fd"]; $this->known_fds[$meta["fd"]] = true; ) ) foreach (self::$restart_fd_props $prop olarak) ( $res[$prop] = $this->$prop; ) return $res;
      Kod, 2 tür özelliğimiz olduğunu dikkate alır:

      1. Bağlantıları olan kaynakları içeren özellikler: $restart_fd_resources = ["read", "write", "streams"].
      2. Ham "serileştirilebilecek" arabellekleri ve diğer bağlantı bilgilerini içeren özellikler: $restart_fd_props = ["read_buf", "write_buf", "conn_count"].
      Ayrıca yeniden başlatma dosyasında saklanan tüm fds'leri hatırlıyoruz ve diğerlerini (varsa) kapatıyoruz, çünkü aksi takdirde dosya tanımlayıcılarını sızdırabiliriz.

      Ardından, bu dosyayı başlangıçta yüklemeli ve hiçbir şey olmamış gibi açık tanımlayıcıları kullanmaya devam etmeliyiz :). İki işlevin kodu (bir yeniden başlatma dosyası yükleme ve dosya tanımlayıcıları hakkında bilgi yükleme) aşağıda gösterilmiştir:

      if (!file_exists(self::RESTART_DIR . self::RESTART_FILENAME)) ( return; ) echo "Dosya yeniden başlatıldı, benimsenmeye çalışılıyor\n"; $contents = file_get_contents(self::RESTART_DIR .self::RESTART_FILENAME); unlink(self::RESTART_DIR . self::RESTART_FILENAME); if ($contents === false) ( fwrite(STDERR, "Yeniden başlatma dosyası okunamadı\n"); dönüş; ) $res = unserialize($contents); if (!$res) ( fwrite(STDERR, "Dosya içeriği yeniden başlatılamadı"); return; ) foreach (self::$restart_props as $prop) ( if (!array_key_exists($prop, $res)) ( fwrite (STDERR, "Yeniden başlatma dosyasında $prop özelliği yok\n"); devam; ) $this->$prop = $res[$prop]; ) $this->loadFdRestartData($res);

      Dosya tanımlayıcı dizisini geri genişletmek için loadFdRestartData() işlevi:

      $fd_resources = ; foreach (self::$restart_fd_resources as $prop) ( if (!isset($res[$prop])) ( fwrite(STDERR, "$prop" özelliği, yeniden başlatma fd kaynaklarında yok\n"); devam; ) $pp = ; foreach ($res[$prop] as $k => $v) ( if (isset($fd_resources[$v])) ( $pp[$k] = $fd_resources[$v]; ) else ( $fp = fopen("php://fd/" . $v, "r+"); if (!$fp) ( fwrite(STDERR, "fd açılamadı = $v, çıkılıyor\n"); çıkış(1); ) stream_set_read_buffer($fp, 0); stream_set_write_buffer($fp, 0); stream_set_blocking($fp, 0); stream_set_timeout($fp, self::CONN_TIMEOUT); $fd_resources[$v] = $fp ; $pp[$k] = $fp; ) ) $this->$prop = $pp; ) foreach (self::$restart_fd_props as $prop) ( if (!isset($res[$prop])) ( fwrite(STDERR, "$prop" özelliği, yeniden başlatma fd özelliklerinde mevcut değil\n"); devam; ) $this->$prop = $res[$prop]; )
      Açık dosya tanımlayıcıları için read_buffer ve write_buffer değerlerini sıfırlıyoruz ve zaman aşımlarını ayarlıyoruz. İşin garibi, bu manipülasyonlardan sonra PHP oldukça sakin bir şekilde bu dosya tanımlayıcıları () kabul eder ve bunların soket olduğunu bilmese de normal şekilde okumaya/yazmaya devam eder.

      Sonunda, işçilerin yürütme durumunu başlatmak ve izlemek için mantığı yazmalıyız. Bu, makalenin konusu ile ilgili olmadığı için, arka plan programının tam uygulaması, aşağıda bağlantısı verilen github deposuna yerleştirilmiştir.

      Çözüm

      Bu nedenle, bu makale JSON protokolü üzerinden iletişim kuran ve yürütme sürecini izleyerek ayrı işlemlerde rastgele sınıflar çalıştırabilen bir arka plan programının uygulanmasını açıklar. Model, bireysel sınıfları çalıştırmak için kullanılır çatal() istek başına, bu nedenle istek, yorumlayıcının yeniden başlatılmasını ve çerçevenin yüklenmesini gerektirmez ve işlem kodu önbelleğini CLI'de kullanmak mümkün olur. Kod her güncellendiğinde arka plan programının yeniden başlatılması gerektiğinden, bu arka plan programını sorunsuz bir şekilde yeniden başlatmak için bir mekanizma sağlamak gerekir (şirketimizde kod güncellemeleri bazen "düzeltmeler" şeklinde birkaç dakikada bir gerçekleşir).

      Yeniden başlatma, tüm çocukların ebeveyne bağlı kalmasına neden olan execve() sistem çağrısı yürütülerek yapılır (çünkü işlemin PID'si execve() sırasında değişmez). Tüm açık dosya tanımlayıcıları da kaydedilir; bu, zaten açık olan bağlantılarda kullanıcılardan gelen istekleri işlemeye devam etmenize olanak tanır. Tüm ağ arabellekleri, çalışan alt öğeler ve açık tanımlayıcılarla ilgili bilgiler, arka plan programının yeni bir örneği tarafından okunan ayrı bir yeniden başlatma dosyasında depolanır, ardından standart olay döngüsünde çalışma devam eder.

      Tam uygulama kodu GitHub'da aşağıdaki adreste görülebilir.