HP server a problémy s real-time

Pavel Troller patrol na sinus.cz
Čtvrtek Duben 14 05:15:16 CEST 2011


Zdravím,
  mám tu zase jeden opravdu zapeklitý případ pro počítačové experty :-).
  Zakoupili jsme na firmě tento server:
        Manufacturer: HP
	Product Name: ProLiant DL120 G6
  Jde o 1U pizzabox, čtyřjádrový xeon @ 2.66 GHz, k tomu hyperthreading,
paměti pro danou aplikaci dostatek (4G).
  Server má sloužit jako telefonní ústředna Asterisk, pro účel čehož je
v něm vložena karta 8xE1 Sangoma.
  Problém je, že server trpí pravidelnými krátkodobými výpadky chodu, kdy
v určitých relativně přesných časových intervalech "mrzne" na dobu až
desítek milisekund a pak se zase rozbíhá. Lépe než slovní popis to vysvětlí
ukázka výpisu maličkého diagnostického prográmku:

Extensive sleep: 2441 usecs.
Freeze interval: 2343820 usecs.
Extensive sleep: 1934 usecs.
Freeze interval: 2343454 usecs.
Extensive sleep: 2145 usecs.
Freeze interval: 2343205 usecs.
Extensive sleep: 1678 usecs.
Freeze interval: 2343493 usecs.
Extensive sleep: 777 usecs.
Freeze interval: 2342056 usecs.
Extensive sleep: 2370 usecs.
Freeze interval: 2345172 usecs.
Extensive sleep: 707 usecs.
Freeze interval: 2341719 usecs.
Extensive sleep: 2077 usecs.
Freeze interval: 2344949 usecs.
Extensive sleep: 1325 usecs.
Freeze interval: 2343499 usecs.
Extensive sleep: 2121 usecs.
Freeze interval: 2343508 usecs.
Extensive sleep: 1311 usecs.
Freeze interval: 2343476 usecs.
Extensive sleep: 2020 usecs.
Freeze interval: 2343395 usecs.
Extensive sleep: 1716 usecs.
Freeze interval: 2343839 usecs.
Extensive sleep: 2101 usecs.
Freeze interval: 2343219 usecs.
Extensive sleep: 1310 usecs.
Freeze interval: 2343460 usecs.
Extensive sleep: 2139 usecs.
Freeze interval: 2343560 usecs.
Extensive sleep: 1815 usecs.
Freeze interval: 2343826 usecs.
Extensive sleep: 2360 usecs.
Freeze interval: 2343387 usecs.

Zdrojový text jest zde:

# cat timetest.c

#include <sys/time.h>
#include <sys/types.h>
#include <sched.h>
#include <stdio.h>

void main () {
  struct timeval tv1,tv2,tv3,tv4;
  int diff, diff2, diff3;
  struct sched_param sp;

  sp.__sched_priority=99;

  if (sched_setscheduler(0, SCHED_FIFO, &sp)) {
        perror("sched_setscheduler failed:");
  }


  gettimeofday(&tv1,0);
  gettimeofday(&tv2,0);
  gettimeofday(&tv3,0);
  gettimeofday(&tv4,0);

  for (;;) {
    gettimeofday(&tv1,0);
    usleep(50);
    gettimeofday(&tv2,0);
    diff=(1000000*tv2.tv_sec+tv2.tv_usec)-(1000000*tv1.tv_sec+tv1.tv_usec);
    if (diff > 500) {
      printf("Extensive sleep: %d usecs.\n",diff);
      diff3=(1000000*tv2.tv_sec+tv2.tv_usec)-(1000000*tv4.tv_sec+tv4.tv_usec);
      if (diff3 > 1000000) {
        tv4=tv2;
        printf("Freeze interval: %d usecs.\n", diff3);
      }
    }
  }
}

Logika je myslím jasná - program se nechá na 50 us uspat a pak si změří, kolik
spal ve skutečnosti. Pokud je to více než 500 us (tj. desetkrát tolik), vypíše
tuto hodnotu a navíc čas, který uplynul od minulého "zaspání". Nu a je vidět,
že k "zaspání" dochází pravidelně po nějakých 2.34 sekundách. Pár dalších
poznámek:

- Prográmek si nastavuje nejvyšší možnou real-time prioritu, nemělo by tedy
existovat nic, co by jej dokázalo dostat od procesoru - vždyť tam jsou 4
plnohodnotná jádra, jedno by mělo být pro něj vždy k dispozici.
- Interval mezi "zaspáními" se v čase nemění, co se ale mění, je délka 
"zaspání", ta v čase vzrůstá. Tato ukázka s průměrnou délkou zaspání 1 - 2 ms
vznikla po cca dvou dnech běhu. Rekord jsem naměřil po 45 dnech, kdy už bylo
jedno každé zaspání od 10 do 30 ms a někdy se stávalo, že v tomto intervalu
se úloha na chvilku "probrala", takže se to vypsalo jako 2 - 3 menší "zaspání"
těsně za sebou.
- Na zaspání se nepodílí chod čehokoliv v systému - test byl měřen, aniž by
běžel jakýkoliv server (včetně toho asterisku), s odpojenými 
a odkonfigurovanými ethernet porty, dokonce se shutdownovanými disky.
- Závada byla již reklamována u výrobce, který vyměnil základní desku. Nová
dělá totéž.
- Bylo testováno několik jader (2.6.34, 36, nyní 38.2) a závada se projevuje
zcela identicky.
- Na solidnějším bratříčkovi tohoto serveru (Proliant DL360 G6) běží zcela
identický software (instalovaný z téhož image) již nějakých 400 dní, aniž by
se uvedená závada jakkoliv projevila. Pokud tam spustím výše uvedený program,
také něco vypisuje, ale jedno zaspání kolem milisekundy se objeví v řádu
desítek hodin, nadto zcela stochasticky. To jsem ochoten tolerovat.
- I můj domácí server, řadové PC od Asusu, s výrazně slabším CPU (běžící
rovněž tentýž image) se chová výrazně lépe, sice "zakopne" častěji než ten
DL360, tak jednou za 4 - 6 hodin, ale opět zcela stochasticky a jen na
krátkou dobu.

Napadá někoho, co tomu krámu je a jak tomu odpomoci ? Velmi hrubý workaround
je stroj každou noc rebootovat, neboť během jednoho dne nenaroste zpoždění
do takových hodnot, že by to vadilo (Asterisk tu milisekundu nedostupnosti
prostě "překlene", i data z těch E1 karet se stačí vyčíst). Je to ale jen
nejvyšší nouze a rozhodně to nehodlám dlouhodobě takto provozovat. 

Taky by mi pomohlo, kdyby by tu byl někdo, kdo provozuje tutéž platformu
a byl by ochoten si tam ten prográmek zkompilovat a na chvilku pustit, abychom
viděli, zda to dělají prostě všechny servery, nebo jen ten náš (přeci jen
nebylo vyměněno vše, např. RAID karta zůstala původní a ta by teoreticky
mohla např. nějakým DMA systém blokovat.

S pozdravem Pavel


Další informace o konferenci Hw-list