Jak zdebugować losowe występowanie 502 - Bad Gateway?

0

Udało mi się (chyba) znaleźć przyczynę. Użyłem do tego xdebug.auto_trace = 1. Po włączeniu tej opcji dostajemy zajebisty trace (domyślnie) w katalogu /tmp. Wystarczy przewinąć na koniec i widzimy, gdzie się wywalił skrypt.


Koduje... koduje i nagle zaczęło mi randomowo wywalać 502. Na dowolnej podstronie. Nie dzieje się to za każdym razem, ale jak radośnie poprzeklikuję się pomiędzy podstronami to po kilku sekundach dostanę 502.

Jak zmienię branch na mastera, albo cofnę się x commitów to problem ustaje, ale póki co nie udało mi się ustalić czy i jaki kawałek kodu jest za to odpowiedzialny. Nie mam pomysłu, bo kod się wywala w takich miejscach, ze nawet nie przechodzi przez zmiany, które wprowadziłem...

Spróbowałem dać die(123) w różnych miejscach aplikacji, w tym na samym końcu akcji w kontrolerze. Do momentu jak die tam był to kod do tego momentu dochodził, ale jak go usunąłem i kliknąłem pare razy f5 to znowu to samo.

Syslog:

Nov  2 14:48:13 foo mysqld[1376]: 2017-11-02 14:48:13 140679083760384 [Warning] Aborted connection 3144 to db: 'foo_prod' user: 'root' host: 'localhost' (Got an error reading communication packets)
Nov  2 14:48:13 foo kernel: [21780.492560] traps: php-fpm7.0[11713] general protection ip:55b8b9d5cc94 sp:7ffc9ba8ca00 error:0 in php-fpm7.0[55b8b9b2a000+3ae000]

Próbowałem zrobić core dump i odczytać zrzut z użyciem gdb, ale okazało się ze dostałem jakieś krzaki, z których nic nie rozumiem (tam chyba powinny być nazwy funkcji?);

#0  0x000055fd8dc23c94 in ?? ()
#1  0x00007ffcc6b098f0 in ?? ()
#2  0x00007fe6d9692d80 in ?? ()
#3  0x00007fe6d965bc00 in ?? ()
#4  0x00007fe6cacc7e30 in ?? ()
#5  0x000055fd8f14f420 in ?? ()
#6  0x0000000000000020 in ?? ()
#7  0x00007ffcc6b09800 in ?? ()
#8  0x00007ffcc6b09808 in ?? ()
#9  0x00007fe6d9692da0 in ?? ()
#10 0x00007fe6d9692d90 in ?? ()
#11 0x00007fe6d97699d8 in ?? ()
#12 0x00007fe600001406 in ?? ()
#13 0x0000000000000165 in ?? ()
#14 0x0000000000000000 in ?? ()

Coś tam wyczytałem ze to może być segmentation fault, ale nie bardzo rozumiem co to, a tym bardziej co to może powodować.

Używam minta 18, nginx, mariadb 10.1, php 7.0.x i phalcona 3.

0

Jak zmienię branch na mastera, albo cofnę się x commitów to problem ustaje

Piszesz w tym momencie o Phalconie, czy czymś innym?

0

Nie o swojej aplikacji. Nie próbowałem zmieniać wersji phalcona, bo uznałem, ze to moja wina (tak jak napisałem, przy zmianie bracha na master problem ustaje - tak mi się wydaje, albo mam pecha i akurat nie występuje, a brak występowania nie jest związany z kodem).

Skłaniam się ku temu, ze mój kod zainicjował problem, bo jak wgrałem zmiany na środowisko testowe, to tam tez zaczęło się dziać to samo.

0

Jeżeli master Twojej aplikacji dobrze działa, tak samo jak cofnięcie się do jakiejś wcześniejszej wersji, to wskazuje, że w Twojej aplikacji jest coś nie tak.

Możesz wkleić kod który sprawia problemy?

0

Chętnie, ale za cholerę nie wiem, który to :D

Próbowałem zrobić checkout HEAD i zakomentowac wszystkie zmiany, które wprowadziłem przez X commitów, ale problem nadal występował.

Najlepsze jest to, ze do końca akcji wszystko działa. Wszystkie najcięższe akcje jak zaczytywanie czegoś z bazy itp. już sie wykonały. Jak nie dam die i kod pójdzie dalej to się wywala. Możliwe, ze plik jakoś złe się zapisał? Nie wiem ze złym encodowaniem czy coś?

A tak poza tym, to dlaczego jak kilka razy odświeże to zaczyna działać? To jest podejrzane dla mnie.

Powalczę jeszcze w domu, jak ochłonę.. bo trochę mnie ten problem wpienił.

1

To ma coś wspólnego z PHQL / Modelami. Tak jak Tobie chyba wczesiej wspomniałem - nie używaj w Phalconie nazw tabel tylko ściezki do klas które są modelami dla danej tabeli SQL.

Np. masz tabelę "product" a jej modelem jest np. \sklep\product\ProductModel, wtedy lepszy jest taki SQL:

SELECT * FROM \sklep\product\ProductModel

niż

SELECT * FROM product

Nalezy pamiętać o backslashu na początku przestrzeni nazw dla klasy czyli \sklep\product\ProductModel a nie sklep\product\ProductModel.

Dodatkowo nie używaj nazw kolumn oryginalnych tylko właściwości z modelu.

Przykładowe mapowanie właściwości do nazw kolumn:

  public function columnMap() {
    
    return array(
        
        'id' => 'id',
        'name' => 'name',
        'php_manager_class' => 'phpManager',
        'profit_margin_pct_default' => 'profitMarginPctDefault',
        'profit_margin_rates' => 'profitMarginRates',
        'properties' => 'properties',
        'active' => 'active',
        'category_map' => 'categoryMap',
        'products_block' => 'productsBlock'
        
        );
  }
0

Phalcon to cachuje? Ta mapę? Bo na początku, przez nieuwagę zrobiłem nazwa kolumny => pusty string i dostałem błąd po czym poprawiłem i CHYBA gdzieś wtedy się zaczęło.

2

Jak najbardziej można włączyć cache dla modeli.

Ja to robię np. tak:

$di->set('modelsMetadata', function () {
          
            
            $metadata = new \Phalcon\Mvc\Model\MetaData\Files(
                [
                    'lifetime' => 86400,
                    'metaDataDir'   => \INOPX_NOPUB_FILE_CACHE_DIR,
                ]
            );
            
            /*$metadata = new \Phalcon\Mvc\Model\MetaData\Session(
                [
                    'lifetime' => 86400
                ]
            );*/

            return $metadata;
        });

Gdzie INOPX_NOPUB_FILE_CACHE_DIR to akurat taka stała moja własna, ale trzeba tam podać ścieżke do katalogu, można też keszować w memcached.

A tutaj keszowanie annotacji:

$di->set('annotations', function () {
          
            
            $metadata = new \Phalcon\Annotations\Adapter\Files(
                [
                    'lifetime' => 86400,
                    'annotationsDir' => \INOPX_NOPUB_ANNOTATION_CACHE_DIR,
                ]
            );

            return $metadata;
        });

Oczywiście ma to sens na produkcyjnym, przy testowaniu keszowanie może przeszkadzać.

Tylko kwestia jest jeszcze taka - że najlepiej nie robić SQL/PHQL z ręki, tylko korzystać z metod find i findFirst jeżeli to możliwe. Później w parametrach jeżeli chcesz po czymś posortować albo zrobić warunek to używasz nazw z właściwości klasy a nie kolumy SQL.

Przykład: kolumna SQL ma nazwę "search_string" a właściwość w klasy która mapuje do tej kolumny to "wyszukiwanie" po polsku, a właściwość której użyjesz do sortowania to "wiek" (w bazie kolumna "age") wtedy:

\sklep\product\ProductModel::find(
"conditions" => "wyszukiwanie = :wyszukiwanie:",
"bind" => ["wyszukiwanie" => 'kasza'],
"orderBy" => 'wiek DESC'
);
1

Nie znam platformy o ktorej mowa, ale zwykle cos takiego szukam przez binary search.

Czyli masz dobra wersje i zla.
Znajdujesz wersje posrodku (w git/svn) i testujesz.
Jesli masz blad - badasz wersje blizej poprawnej. Jesli nie ma bledu - badasz wersje blizej blednej.
I tak w kolko az dochodzisz do konkretnego commita.

Potem szukasz konkretnie pliku ktorego zmiana powoduje blad.

Potem linii.

A jesli chodzi o samo testowanie to mozesz wykorzystac jakis stress tester, np Apache JMeter.

Uwaga: blad moze sie nie pojawic przy die / echo.
Lepiej wtedy logowac do pliku.

0

@TomRZ: debuggerem podczas sesji gdy występuje błąd dochodzę do widoku (pliku .volt, a raczej .php :P), czy eliminuje to problem z baza?

1

Niekoniecznie, zależy co w tym widoku masz. Trudno wróżyć z fusów, najlepiej gdybyś wkleił kod widoku. Przy czym ja nie korzystam z volta, widoki robię w czystym PHP.

Na marginesie: naprawdę nie rozumiem za bardzo sensu używania takich wynalazków jak volt, smarty, czy inne systemy szablonów. NIe dość, że trzeba się uczyć dodatkowej składni np. pętli, to w dodatku wszystko to co "daje" taki system szablonów (np. keszowanie) można bez problemu osiągnąć w czystym PHP / funkcjami frameworka. Jedyny ewentualny sens jest wtedy, kiedy ktoś inny miesza w szblonach, i chcemy mu ograniczyć prawa.

0

@TomRZ: Chyba znalazłem.

class Tag extends \Phalcon\Tag
{
    public static function getUrlService()
    {
        self::$_urlService = self::getDI()->get('url');

        return self::$_urlService;
    }
}

Jak to wywale, to wydaje się działać. W tej metodzie chyba chodzi o to, żeby nie cacheować serwisu, tak jak robi to Phalcon (L189), bo ->get('url') zwraca obiekt typu UrlInterface.

Masz jakiś pomysł dlaczego? I dlaczego do diabła tylko czasami się to wykrzacza?

Ostatni wpis w trace:

-> Phalcon\Mvc\Url->setDI() /home/vagrant/Code/xxx/apps/Plugins/Tag.php:15 (15 to self::$_urlService = self::getDI()->get('url');)

Jak rozkminie czemu to powoduje segmentation fault to dam znać..

0

Di pobieraj przez \Phalcon\Di::getDefault() czy jakoś tak - w każdym razie statyczną metodą

1

To chyba coś z phalconem/zephirem.
https://github.com/phalcon/zephir/issues/1596

1 użytkowników online, w tym zalogowanych: 0, gości: 1