<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Athlan • Piotr Pelczar • blog programisty &#187; Server</title>
	<atom:link href="http://athlan.pl/kategoria/server/feed/" rel="self" type="application/rss+xml" />
	<link>http://athlan.pl</link>
	<description>Napisać kod zrozumiały dla komputera potrafi byle głupek. Dobrzy programiści tworzą kod zrozumiały dla człowieka...</description>
	<lastBuildDate>Tue, 14 Feb 2012 14:33:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>PHP cache, semafory</title>
		<link>http://athlan.pl/php-cache-semafory/</link>
		<comments>http://athlan.pl/php-cache-semafory/#comments</comments>
		<pubDate>Sat, 11 Jun 2011 22:11:46 +0000</pubDate>
		<dc:creator>Athlan</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Optymalizacja]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Planeta]]></category>
		<category><![CDATA[Przemyślenia]]></category>
		<category><![CDATA[Publikacje]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[Solutions]]></category>

		<guid isPermaLink="false">http://athlan.pl/?p=728</guid>
		<description><![CDATA[Praktyka cache&#8216;owania danych jest powszechna wśród programistów aplikacji webowych ze względu na optymalizację dostępu do danych bezpośrednio ze źródła ich pochodzenia, a w szczególności: trudność dostępu (np. wykonanie skomplikowanych połączeń), ograniczenia dostępu (np. limit odpytywania), długi czas oczekiwania na dane; powodów jest wiele. O ile tematyką stworzenia samego mechanizmu cache zajęli się m.in. Nospor, możecie [...]]]></description>
			<content:encoded><![CDATA[<p>Praktyka <strong>cache</strong>&#8216;owania danych jest powszechna wśród programistów aplikacji webowych ze względu na optymalizację dostępu do danych bezpośrednio ze źródła ich pochodzenia, a w szczególności:</p>
<ul>
<li>trudność dostępu (np. wykonanie skomplikowanych połączeń),</li>
<li>ograniczenia dostępu (np. limit odpytywania),</li>
<li>długi czas oczekiwania na dane; powodów jest wiele.</li>
</ul>
<p>O ile tematyką stworzenia samego mechanizmu cache zajęli się m.in. <a href="http://forum.php.pl/klasa-Cache-t49472.html" rel="nofollow">Nospor</a>, możecie podejrzeć jak to wygląda w <a href="http://framework.zend.com/manual/en/zend.cache.html" rel="nofollow">Zend_Cache</a>, Symfony, czy <a href="http://docs.kohanaphp.com/libraries/cache" rel="nofollow">Kohana</a>; tak ja chciałbym zwrócić uwagę na jeszcze jedną rzecz.</p>
<p>Zazwyczaj schemat kodu wygląda mniej więcej tak:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #000088;">$oCache</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Cache<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// tworzony jest jakis obiekt cache</span>
&nbsp;
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$oCache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">expired</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">3600</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aData</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$oCache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// sprawdzamy, czy jest cache i nie wygasł</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$aData</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$oModel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">GetSomething</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// zbieramy dane z bazy danych</span>
  <span style="color: #000088;">$oCache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aData</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// $aData przechowuje nasze dane do użytku</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<h2>Symulacja, parę linijek kodu, a ile nieszczęść.</h2>
<p>Wszystko działa pięknie, dopóki nie spotkamy się z sytuacją, gdy setki osób (procesów) jednocześnie zechcą zbierać takie dane z bazy danych. Przeprowadźmy zatem krótką dywagację. Załóżmy, że użytkownik #1 wchodzi na stronę, stwierdza, że nie ma cache, lub jest nieświeży, wówczas przechodzi do połączenia się z bazą danych i zaczyna zbierać dane. W tym samym czasie, zanim użytkownikowi #1 zostaną zwrócone dane wchodzi użytkownik #2, który stwierdza, że nie ma cache, bo użytkownik #1 jeszcze nie zebrał danych, postanawia połączyć się z bazą i zrobić to samo, co użytkownik #1, powtarzając niepotrzebnie czynność i dodatkowo obciążając bazę. Można by iść dalej i wprowadzić <em>n</em> użytkowników, którzy powtarzają czynność, dopóki dane nie pojawią się w cache i kolejni użytkownicy będą z niego korzystać. Co się stanie natomiast, gdy kolejka tak narośnie, że użytkownikowi #1 zabraknie zasobów systemowych, aby ukończyć proces zbierania danych, co spowoduje, że pozostałym też? Kolejka będzie wydłużała się w nieskończoność, póki system operacyjny nie podejmie żadnych działań (np. odłączy bazę danych, lub po prostu wyłączy serwer, np. w <a href="http://pl.wikipedia.org/wiki/IIS" rel="nofollow">IIS7</a> wyłączy cały application pool). Aby doszło do tej kolizji nie jest potrzebne wcale natężenie użytkowników, serwer może akurat np. zajmować się wysyłką maili lub nieoptymalnie zrobionym procesem, który zajmuje zasoby, a w tym czasie wejdzie tylko pięciu użytkowników.</p>
<p>Parę linijek kodu, a ile nieszczęść.</p>
<h2>Pojęcie semafora.</h2>
<blockquote><p>Semafor w informatyce &#8211; jest chronioną zmienną lub abstrakcyjnym typem danych, który stanowi klasyczną metodę kontroli dostępu przez wiele procesów do wspólnego zasobu w środowisku programowania równoległego.</p></blockquote>
<p>Więcej na temat semaforów na <a href="http://pl.wikipedia.org/wiki/Semafor_(informatyka)" rel="nofollow">Wikipedii</a>, bądź w <em>Podstawy informatyki / Stefan Węgrzyn. &#8211; Warszawa : Państwowe Wydawnictwo Naukowe, 1982</em>.</p>
<h2>Podejście do problemu.</h2>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #000088;">$oCache</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Cache<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$oCache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">expired</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">3600</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aData</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$oCache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$oCache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">savePrepare</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// stawiamy semafor</span>
&nbsp;
  <span style="color: #000088;">$aData</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$oModel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">GetSomething</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$oCache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aData</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// metoda save() może (nie musi) od razu zwolnić semafor, gdy próba zapisu się zakończy</span>
  <span style="color: #666666; font-style: italic;">// jeżeli metoda save() nie zwalnia zasobu, możemy np. użyć:</span>
  <span style="color: #666666; font-style: italic;">// $oCache-&gt;saveFinalize();</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// $aData przechowuje nasze dane do użytku</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Rozwiązaniem jest zastosowanie <strong>semafora</strong> blokującego dostęp do zasobu (w tym przypadku abstrakcyjnie &#8220;cache&#8221;, mniej abstrakcyjnie może być to plik na dysku, przestrzeń w pamięci operacyjnej, rekord w bazie danych, cokolwiek, co cache przerzymuje). Dla wartości semafora = 1 zasób jest wolny (nieużywany, jest 1 cache), gdy jest mniejszy/równy 0 zasób jest zajęty, ktoś z niego &#8220;korzysta&#8221;. Zajętość zasobu powinna być sprawdzana przy próbie odczytu. Dopóki zasób nie zostanie zwolniony, nie będzie można określić, czy są dane w cache. Jeżeli nie można określić, czy dane są w cache, należy zaczekać na zwolnienie zasobu.</p>
<p>Teraz nasze rozwiązanie nie dopuści do przytoczonej w powyższym przykładzie sytuacji. Zanim cache nie zostanie odblokowany po próbie zapisu, nie uzyskamy odczytu, czekając na niego i nie przechodząc w skrypcie nigdzie dalej.</p>
<p>Gdy <code>save()</code> się nie powiedzie? Można zastosować timeouty odczytu na <code>load()</code>. Wówczas złapalibyśmy wyjątek i przeszli dalej do realizacji zapisu, tak, jakby semafora nie było.</p>
<h2>Implementacja.</h2>
<p>Do swoich kodów podchodzę jak najbardziej abstrakcyjnie (tutaj idealnie nada się <a href="http://pl.wikipedia.org/wiki/Fabryka_abstrakcyjna_(wzorzec_projektowy)">wzorzec fabryki</a>), zatem stworzyłem klasę <em>Cache</em>, która obsługuje &#8216;silniki&#8217; implementujące interfejs <em>Cache_Engine</em>. Jednym z nich jest silnik <em>Cache_Engine_File</em>, który wykorzystuje pliki na dysku do składowania cache.</p>
<p>Najprostszym semaforem dla plików jest funkcja <code><a href="http://php.net/flock">flock()</a></code> (gotowe, sprawdzone rozwiązanie, w dodatku na poziomie systemu plików, nic tylko implementować). Sprawa wygląda bardzo prosto, dopóki nie zwolnimy flagi <code>LOCK_EX</code> po jej założeniu, ludzie nie będą czytali z pliku, czekając na zwolnienie dostępu. Ktoś powie: truizm, blokować pliki powinno się przed wykonywaniem na nich operacji. Tak. Ale grunt, w którym miejscu to zablokowanie nastąpi. Wykorzystujemy blokowanie do wyższego celu.</p>
<p>Wg. dokumentacji nie można polegać na <code>flock()</code> w przypadku Windows98 oraz systemów FAT32. Zbyt dużym poziomem abstrakcji jest dla mnie stawianie serwisu na pamięci flash lub Win98, ale faktycznie, najprostsza pamięć flash z systemem FAT32 może się czasem zdarzyć w serwerowniach i nie jest to wcale taki głupi pomysł. Co wtedy? Jako semafor możemy stworzyć plik z suffiksem <em>.lock</em> obok tworzonego pliku cache. Gdy plik istnieje oznacza to, że cache jest zablokowany, jeżeli nie &#8211; jest wolny. Czekamy tak długo, aż zostanie usunięty plik <em>.lock</em>.</p>
<h2>Przykładowy kod źródłowy.</h2>
<p>Przykładowy kod źródłowy obsługuje <em>Cache_Engine_File</em> oraz <em>Cache_Engine_Filelock</em>, gdzie w drugim przypadku można klasy użyć spokojnie na partycjach FAT32. Kod jest przykładowy, dlatego nie obsługuje m.in. zagnieżdżania plików w katalogach, usuwanie cache&#8217;u itd, zaimplementowałem tylko zapis i odczyt.</p>
<p>Klasy zostały napisane tak, aby zgłaszane przez nie błędy były <a href="http://www.php.net/manual/en/spl.exceptions.php">zgodnie z ideologią hierarchiczną Exceptions w PHP</a>, przy okazji zapraszam do lektury wpisu <a href="http://www.zyxist.com/pokaz.php/wyjatki_w_php">&#8220;Wyjątki w PHP&#8221;</a> autorstwa Tomasza Jędrzejewskiego (Zyxits).</p>
<ul>
<li><a href="http://athlan.pl/code/lib-cache/Cache">Klasa Cache</a>, Cache_Exception, abstrakcja Cache_Engine</li>
<li><a href="http://athlan.pl/code/lib-cache/Cache/Engine/File">Klasa Cache_Engine_File</a>, która bazuje na plikach</li>
<li><a href="http://athlan.pl/code/lib-cache/Cache/Engine/Filelock">Klasa Cache_Engine_Filelock</a>, która bazuje na plikach + tworzy pliki <em>.lock</em></li>
</ul>
<p>Przykładowe czekanie na zwolnienie pliku <em>.lock</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span> ?php
&nbsp;
<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> _waitUnlock<span style="color: #009900;">&#40;</span><span style="color: #000088;">$iWaitTimeout</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$iWaitTimeout</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    try
    <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">// quick first check</span>
      <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">is_file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_path<span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'lock'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// wait for unlock file</span>
        <span style="color: #000088;">$iWaitTimeout</span> <span style="color: #339933;">/=</span> <span style="color: #cc66cc;">1000000</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$iLockTime</span> <span style="color: #339933;">=</span> <span style="color: #990000;">microtime</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$bLockWait</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// wait for the file</span>
        try
        <span style="color: #009900;">&#123;</span>
          <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">is_file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_path<span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'lock'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
          <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$iLockWaitDelta</span> <span style="color: #339933;">=</span> <span style="color: #990000;">microtime</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #000088;">$iLockTime</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$iLockWaitDelta</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$iWaitTimeout</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$iWaitTimeout</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>
              <span style="color: #009900;">&#123;</span> <span style="color: #000088;">$bLockWait</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span> <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
            <span style="color: #990000;">usleep</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">rand</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">999</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
          <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #666666; font-style: italic;">// cache lock path does not exists</span>
        catch<span style="color: #009900;">&#40;</span>Cache_Exception_Runtime <span style="color: #000088;">$oE</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$bLockWait</span><span style="color: #009900;">&#41;</span>
          <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Cache_Exception_Runtime<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Unable to access cache, it is totally locked, after &quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$iWaitTimeout</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot; s.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #666666; font-style: italic;">// cache lock path does not exists</span>
    catch<span style="color: #009900;">&#40;</span>Cache_Exception_Runtime <span style="color: #000088;">$oE</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #b1b100;">else</span>
  <span style="color: #009900;">&#123;</span>
    try
    <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">is_file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_path<span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'lock'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Cache_Exception_Runtime<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Unable to access cache, it is currently locked, after &quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$iWaitTimeout</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot; s.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #666666; font-style: italic;">// cache path does not exists</span>
    catch<span style="color: #009900;">&#40;</span>Cache_Exception_Runtime <span style="color: #000088;">$oE</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://athlan.pl/php-cache-semafory/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Automatyczny restart Apache</title>
		<link>http://athlan.pl/automatyczny-restart-apache/</link>
		<comments>http://athlan.pl/automatyczny-restart-apache/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 13:19:44 +0000</pubDate>
		<dc:creator>Athlan</dc:creator>
				<category><![CDATA[Planeta]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[crash]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[restart]]></category>
		<category><![CDATA[timeout]]></category>
		<category><![CDATA[wget]]></category>

		<guid isPermaLink="false">http://athlan.pl/?p=224</guid>
		<description><![CDATA[Wiele razy zdarzało mi się, że mój serwer padł całkowicie lub przerywał żądania. Wówczas był niedostępny, a zarobki generowane z serwisów diametralnie spadały. Co więcej&#8230; użytkownicy poczuli niestabilność maszyny. Dziś po odpowiedniej optymalizacji kodów aplikacji pady są rzadkością, ale wolę się ubezpieczyć przed niespodziewanym downem serwera. Problem można rozwiązać w prosty sposób: cyklicznie uruchamiany program [...]]]></description>
			<content:encoded><![CDATA[<p>Wiele razy zdarzało mi się, że mój serwer padł całkowicie lub przerywał żądania. Wówczas był niedostępny, a zarobki generowane z serwisów diametralnie spadały. Co więcej&#8230; użytkownicy poczuli niestabilność maszyny. Dziś po odpowiedniej optymalizacji kodów aplikacji pady są rzadkością, ale wolę się ubezpieczyć przed niespodziewanym downem serwera.</p>
<p>Problem można rozwiązać w prosty sposób: cyklicznie uruchamiany program <a href="http://pl.wikipedia.org/wiki/Bash">bash</a>&#8216;a przez <a href="http://pl.wikipedia.org/wiki/Cron_(Unix)">cron</a>a będzie odpowiadał za poprawne działanie usługi apache. Listing, który zaprezentuję łączy się z adresem url odwołującym się do naszego serwera za pomocą <a href="http://www.gnu.org/software/wget/wget.html"><code>wget</code></a>, a następnie wynik działania (response body) zapisze do pliku tymczasowego. Jeżeli plik istnieje oraz ma rozmiar niezerowy, oznacza to, że serwer działa poprawnie. Jeżeli plik nie istnieje, bądź jego wielkość jest równa zero z, oznacza to, że trzeba zrestartować usługę apache, bo nie odpowiada. Zaraz przed zakończeniem programu, plik tymczasowy powinien zostać usunięty. Pozwoliłem sobie opublikować mały <a href="http://athlan.pl/code/CheckApache">program służący do automatycznego restartu usługi apache</a>.</p>
<p>Aby nasz program poprawnie działał, trzeba zastanowić się nad trzema istotnymi rzeczami:</p>
<ol>
<li>Ile prób połączenia ma wykonać <code>wget</code> oraz jakie mogę być timeouty.</li>
<li>Czy adres url, do którego się odwołujemy będzie zawsze dostępny w przypadku poprawnego działania usługi apache.</li>
<li>Jaki powinien być interwał uruchamiania napisanego programu.</li>
</ol>
<p>Na moim serwerze program uruchamia się co minutę, próbuje połączyć się ze stroną dwa razy, a maksymalny czas oczekiwania na odpowiedź przy każdej z prób wynosi 10 sekund.</p>
<p>Program zapisany jest pod <code>/root/check_apache.sh</code>, a regułka uruchamiania w cronie wygląda następująco:</p>
<pre>* * * * *       bash /root/check_apache.sh</pre>
<p><span style="color: #999999;">Przedstawiony problem można rozwiązać na wiele sposobów, przedstawiłem ten najbardziej oczywisty.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://athlan.pl/automatyczny-restart-apache/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Upload filmów z Zend_Gdata_YouTube</title>
		<link>http://athlan.pl/upload-filmow-zend_gdata_youtube/</link>
		<comments>http://athlan.pl/upload-filmow-zend_gdata_youtube/#comments</comments>
		<pubDate>Sat, 20 Dec 2008 14:00:56 +0000</pubDate>
		<dc:creator>Athlan</dc:creator>
				<category><![CDATA[Planeta]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Przemyślenia]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[Zend framework]]></category>
		<category><![CDATA[gdata]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[youtube]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://athlan.pl/?p=148</guid>
		<description><![CDATA[Pisząc nowy projekt natknąłem na problem z procesem uploadu filmiku do serwisu YouTube. Sam upload jest bardzo łatwy do napisania z Zend_Gdata_YouTube &#8211; przykład można znaleźć w manualu. Myślę, że zainteresowani przeczytają manual i wszystko będzie jasne. Więc jeżeli to takie proste, to w czym problem? Zakładamy, że userzy uloadują filmiki bezpośrednio na nasz serwis. [...]]]></description>
			<content:encoded><![CDATA[<p>Pisząc <a href="http://athlan.pl/videoblog/">nowy projekt</a> natknąłem na problem z procesem uploadu filmiku do serwisu YouTube. Sam upload jest bardzo łatwy do napisania z <a href="http://framework.zend.com/apidoc/core/Zend_Gdata/App/Zend_Gdata_YouTube.html">Zend_Gdata_YouTube</a> &#8211; <a href="http://framework.zend.com/manual/en/zend.gdata.youtube.html#zend.gdata.youtube.uploads.example">przykład</a> można znaleźć w manualu. Myślę, że zainteresowani przeczytają manual i wszystko będzie jasne. Więc jeżeli to takie proste, to w czym problem?</p>
<p>Zakładamy, że userzy uloadują filmiki bezpośrednio na nasz serwis. Nasz serwer ma za zadanie:</p>
<ol>
<li>Skompresować video i zapisać go w formacie flv.</li>
<li>Nałożyć watermark.</li>
<li>Wysłać obrobiony film do serwisu Youtube logując się na zdefiniowane przez użytkownika konto lub założone przez administratora strony.</li>
</ol>
<p>Pierwsze 2 kroki wykonają się błyskawicznie w porównaniu do trzeciego. Kompresja i nałożenie watermarku na 30 megowy plik z wykorzystaniem FFMPEG to nic nadzwyczajnego. Natomiast wysyłka pliku na serwery Youtube&#8217;a może zawiesić apache&#8217;a, gdy jest ich kilka.</p>
<p>Rozwiązanie? Wpadłem na pomysł, aby upload filmików ustawiony był w pewnego rodzaju kolejce, która uruchamiana by była co minutę (cron), a czas jednego wysłania elemntu nie mógłby przekroczyć 50 sekund. Oczywiście takie działanie uruchamiałoby swój osobny proces apache&#8217;a. Ten sposób jest ograniczony dwoma limitami: wielkością pliku oraz czasem jego uploadu na serwer (jednocześniem interwałem uruchamiania kolejki).</p>
]]></content:encoded>
			<wfw:commentRss>http://athlan.pl/upload-filmow-zend_gdata_youtube/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->
