เช•เซเชฒเชธเซเชŸเชฐ เชฎเชพเชŸเซ‡ เชคเชฎเชพเชฐเซเช‚ เชชเซ‹เชคเชพเชจเซเช‚ เช“เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฌเชจเชพเชตเชตเซเช‚

เชจเชฎเชธเซเชคเซ‡! เช…เชฎเซ‡ เชฒเซ‹เช•เซ‹เชจเซ‡ เชฎเซ‹เชŸเชพ เชกเซ‡เชŸเชพ เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชตเชพเชจเซ€ เชคเชพเชฒเซ€เชฎ เช†เชชเซ€เช เช›เซ€เช. เชคเซ‡เชจเชพ เชชเซ‹เชคเชพเชจเชพ เช•เซเชฒเชธเซเชŸเชฐ เชตเชฟเชจเชพ เชฎเซ‹เชŸเชพ เชกเซ‡เชŸเชพ เชชเชฐ เชถเซˆเช•เซเชทเชฃเชฟเช• เชชเซเชฐเซ‹เช—เซเชฐเชพเชฎเชจเซ€ เช•เชฒเซเชชเชจเชพ เช•เชฐเชตเซ€ เช…เชถเช•เซเชฏ เช›เซ‡, เชœเซ‡เชจเชพ เชชเชฐ เชฌเชงเชพ เชธเชนเชญเชพเช—เซ€เช“ เชธเชพเชฅเซ‡ เชฎเชณเซ€เชจเซ‡ เช•เชพเชฎ เช•เชฐเซ‡ เช›เซ‡. เช† เช•เชพเชฐเชฃเซ‹เชธเชฐ, เช…เชฎเชพเชฐเชพ เชชเซเชฐเซ‹เช—เซเชฐเชพเชฎเชฎเชพเช‚ เชนเช‚เชฎเซ‡เชถเชพ เชคเซ‡ เชนเซ‹เชฏ เช›เซ‡ ๐Ÿ™‚ เช…เชฎเซ‡ เชคเซ‡เชจเชพ เชฐเซ‚เชชเชฐเซ‡เช–เชพเช‚เช•เชจ, เชŸเซเชฏเซเชจเชฟเช‚เช— เช…เชจเซ‡ เชตเชนเซ€เชตเชŸเชฎเชพเช‚ เชฐเซ‹เช•เชพเชฏเซ‡เชฒเชพ เช›เซ€เช, เช…เชจเซ‡ เชฒเซ‹เช•เซ‹ เชธเซ€เชงเชพ เชœ เชคเซเชฏเชพเช‚ MapReduce เชจเซ‹เช•เชฐเซ€เช“ เชถเชฐเซ‚ เช•เชฐเซ‡ เช›เซ‡ เช…เชจเซ‡ เชธเซเชชเชพเชฐเซเช•เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ‡ เช›เซ‡.

เช† เชชเซ‹เชธเซเชŸเชฎเชพเช‚ เช…เชฎเซ‡ เชคเชฎเชจเซ‡ เชœเชฃเชพเชตเซ€เชถเซเช‚ เช•เซ‡ เช…เชฎเซ‡ เช•เซเชฒเชพเช‰เชกเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช…เชฎเชพเชฐเซเช‚ เชชเซ‹เชคเชพเชจเซเช‚ เช“เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐ เชฒเช–เซ€เชจเซ‡ เช…เชธเชฎเชพเชจ เช•เซเชฒเชธเซเชŸเชฐ เชฒเซ‹เชกเชฟเช‚เช—เชจเซ€ เชธเชฎเชธเซเชฏเชพเชจเซ‡ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชนเชฒ เช•เชฐเซ€. Mail.ru เช•เซเชฒเชพเช‰เชก เชธเซ‹เชฒเซเชฏเซเชถเชจเซเชธ.

เชธเชฎเชธเซเชฏเชพ

เช…เชฎเชพเชฐเชพ เช•เซเชฒเชธเซเชŸเชฐเชจเซ‹ เช‰เชชเชฏเซ‹เช— เชฒเชพเช•เซเชทเชฃเชฟเช• เชฎเซ‹เชกเชฎเชพเช‚ เชฅเชคเซ‹ เชจเชฅเซ€. เชจเชฟเช•เชพเชฒ เช…เชคเซเชฏเช‚เชค เช…เชธเชฎเชพเชจ เช›เซ‡. เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เชคเซเชฏเชพเช‚ เชชเซเชฐเชพเชฏเซ‹เช—เชฟเช• เชตเชฐเซเช—เซ‹ เช›เซ‡, เชœเซเชฏเชพเชฐเซ‡ เชฌเชงเชพ 30 เชฒเซ‹เช•เซ‹ เช…เชจเซ‡ เชเช• เชถเชฟเช•เซเชทเช• เช•เซเชฒเชธเซเชŸเชฐเชฎเชพเช‚ เชœเชพเชฏ เช›เซ‡ เช…เชจเซ‡ เชคเซ‡เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชจเซเช‚ เชถเชฐเซ‚ เช•เชฐเซ‡ เช›เซ‡. เช…เชฅเชตเชพ เชซเชฐเซ€เชฅเซ€, เชธเชฎเชฏเชฎเชฐเซเชฏเชพเชฆเชพ เชชเชนเซ‡เชฒเชพเชจเชพ เชฆเชฟเชตเชธเซ‹ เชนเซ‹เชฏ เช›เซ‡ เชœเซเชฏเชพเชฐเซ‡ เชฒเซ‹เชก เชฎเซ‹เชŸเชพ เชชเซเชฐเชฎเชพเชฃเชฎเชพเช‚ เชตเชงเซ‡ เช›เซ‡. เชฌเชพเช•เซ€เชจเซ‹ เชธเชฎเชฏ เช•เซเชฒเชธเซเชŸเชฐ เช…เชจเซเชกเชฐเชฒเซ‹เชก เชฎเซ‹เชกเชฎเชพเช‚ เช•เชพเชฐเซเชฏ เช•เชฐเซ‡ เช›เซ‡.

เชธเซ‹เชฒเซเชฏเซเชถเชจ #1 เช เชเช• เช•เซเชฒเชธเซเชŸเชฐ เชฐเชพเช–เชตเชพเชจเซเช‚ เช›เซ‡ เชœเซ‡ เชชเซ€เช• เชฒเซ‹เชกเชจเซ‹ เชธเชพเชฎเชจเซ‹ เช•เชฐเชถเซ‡, เชชเชฐเช‚เชคเซ เชฌเชพเช•เซ€เชจเชพ เชธเชฎเชฏเซ‡ เชจเชฟเชทเซเช•เซเชฐเชฟเชฏ เชฐเชนเซ‡เชถเซ‡.

เชธเซ‹เชฒเซเชฏเซเชถเชจ #2 เช เชเช• เชจเชพเชจเซเช‚ เช•เซเชฒเชธเซเชŸเชฐ เชฐเชพเช–เชตเซเช‚ เช›เซ‡, เชœเซ‡เชฎเชพเช‚ เชคเชฎเซ‡ เชตเชฐเซเช—เซ‹ เชชเชนเซ‡เชฒเชพเช‚ เช…เชจเซ‡ เชชเซ€เช• เชฒเซ‹เชก เชฆเชฐเชฎเชฟเชฏเชพเชจ เชฎเซ‡เชจเซเชฏเซเช…เชฒเซ€ เชจเซ‹เชกเซเชธ เช‰เชฎเซ‡เชฐเซ‹ เช›เซ‹.

เชธเซ‹เชฒเซเชฏเซเชถเชจ #3 เช เชเช• เชจเชพเชจเซเช‚ เช•เซเชฒเชธเซเชŸเชฐ เชฐเชพเช–เชตเซเช‚ เช…เชจเซ‡ เช“เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐ เชฒเช–เชตเชพเชจเซเช‚ เช›เซ‡ เชœเซ‡ เช•เซเชฒเชธเซเชŸเชฐเชจเชพ เชตเชฐเซเชคเชฎเชพเชจ เชฒเซ‹เชกเชจเซ‡ เชฎเซ‹เชจเชฟเชŸเชฐ เช•เชฐเชถเซ‡ เช…เชจเซ‡, เชตเชฟเชตเชฟเชง API เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡, เช•เซเชฒเชธเซเชŸเชฐเชฎเชพเช‚เชฅเซ€ เชจเซ‹เชกเซเชธ เช‰เชฎเซ‡เชฐเซ‹ เช…เชจเซ‡ เชฆเซ‚เชฐ เช•เชฐเชถเซ‡.

เช† เชชเซ‹เชธเซเชŸเชฎเชพเช‚ เช†เชชเชฃเซ‡ เช‰เช•เซ‡เชฒ เชจเช‚เชฌเชฐ 3 เชตเชฟเชถเซ‡ เชตเชพเชค เช•เชฐเซ€เชถเซเช‚. เช† เช“เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐ เช†เช‚เชคเชฐเชฟเช• เชชเชฐเชฟเชฌเชณเซ‹เชจเซ‡ เชฌเชฆเชฒเซ‡ เชฌเชพเชนเซเชฏ เชชเชฐเชฟเชฌเชณเซ‹ เชชเชฐ เช–เซ‚เชฌ เชœ เชจเชฟเชฐเซเชญเชฐ เช›เซ‡, เช…เชจเซ‡ เชชเซเชฐเชฆเชพเชคเชพเช“ เช˜เชฃเซ€เชตเชพเชฐ เชคเซ‡ เชชเซเชฐเชฆเชพเชจ เช•เชฐเชคเชพ เชจเชฅเซ€. เช…เชฎเซ‡ Mail.ru เช•เซเชฒเชพเช‰เชก เชธเซ‹เชฒเซเชฏเซเชถเชจเซเชธ เช•เซเชฒเชพเช‰เชก เชˆเชจเซเชซเซเชฐเชพเชธเซเชŸเซเชฐเช•เซเชšเชฐเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เช เช›เซ€เช เช…เชจเซ‡ MCS API เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เช‘เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐ เชฒเช–เซ€เช เช›เซ€เช. เช…เชจเซ‡ เช…เชฎเซ‡ เชกเซ‡เชŸเชพ เชธเชพเชฅเซ‡ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช•เชพเชฎ เช•เชฐเชตเซเช‚ เชคเซ‡ เชถเซ€เช–เชตเชคเชพ เชนเซ‹เชตเชพเชฅเซ€, เช…เชฎเซ‡ เชคเซ‡ เชฌเชคเชพเชตเชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซเชฏเซเช‚ เช•เซ‡ เชคเชฎเซ‡ เชคเชฎเชพเชฐเชพ เชชเซ‹เชคเชพเชจเชพ เชนเซ‡เชคเซเช“ เชฎเชพเชŸเซ‡ เชธเชฎเชพเชจ เช“เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฒเช–เซ€ เชถเช•เซ‹ เช›เซ‹ เช…เชจเซ‡ เชคเซ‡เชจเซ‹ เช‰เชชเชฏเซ‹เช— เชคเชฎเชพเชฐเชพ เช•เซเชฒเชพเช‰เชก เชธเชพเชฅเซ‡ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹.

เชชเซ‚เชฐเซเชตเชœเชฐเซ‚เชฐเซ€เชฏเชพเชคเซ‹

เชชเซเชฐเชฅเชฎ, เชคเชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ Hadoop เช•เซเชฒเชธเซเชŸเชฐ เชนเซ‹เชตเซเช‚ เช†เชตเชถเซเชฏเช• เช›เซ‡. เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เช…เชฎเซ‡ HDP เชตเชฟเชคเชฐเชฃเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เช เช›เซ€เช.

เชคเชฎเชพเชฐเชพ เชจเซ‹เชกเซเชธ เชเชกเชชเชฅเซ€ เช‰เชฎเซ‡เชฐเชตเชพ เช…เชจเซ‡ เชฆเซ‚เชฐ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, เชคเชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ เชจเซ‹เชกเซเชธ เชตเชšเซเชšเซ‡ เชญเซ‚เชฎเชฟเช•เชพเช“เชจเซเช‚ เชšเซ‹เช•เซเช•เชธ เชตเชฟเชคเชฐเชฃ เชนเซ‹เชตเซเช‚ เช†เชตเชถเซเชฏเช• เช›เซ‡.

  1. เชฎเชพเชธเซเชŸเชฐ เชจเซ‹เชก. เช เซ€เช• เช›เซ‡, เช–เชพเชธ เช•เชฐเซ€เชจเซ‡ เช•เช‚เชˆเชชเชฃ เชธเชฎเชœเชพเชตเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เชจเชฅเซ€: เช•เซเชฒเชธเซเชŸเชฐเชจเซ‹ เชฎเซเช–เซเชฏ เชจเซ‹เชก, เชœเซ‡เชจเชพ เชชเชฐ, เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เชœเซ‹ เชคเชฎเซ‡ เช‡เชจเซเชŸเชฐเซ‡เช•เซเชŸเชฟเชต เชฎเซ‹เชกเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ‹ เช›เซ‹, เชคเซ‹ เชธเซเชชเชพเชฐเซเช• เชกเซเชฐเชพเช‡เชตเชฐ เชถเชฐเซ‚ เชฅเชพเชฏ เช›เซ‡.
  2. เชคเชพเชฐเซ€เช– เชจเซ‹เชก. เช† เช เชจเซ‹เชก เช›เซ‡ เช•เซ‡ เชœเซ‡เชจเชพ เชชเชฐ เชคเชฎเซ‡ HDFS เชชเชฐ เชกเซ‡เชŸเชพ เชธเซเชŸเซ‹เชฐ เช•เชฐเซ‹ เช›เซ‹ เช…เชจเซ‡ เชœเซเชฏเชพเช‚ เช—เชฃเชคเชฐเซ€เช“ เชฅเชพเชฏ เช›เซ‡.
  3. เช•เชฎเซเชชเซเชฏเซเชŸเชฟเช‚เช— เชจเซ‹เชก. เช† เชเช• เชจเซ‹เชก เช›เซ‡ เชœเซเชฏเชพเช‚ เชคเชฎเซ‡ HDFS เชชเชฐ เช•เช‚เชˆเชชเชฃ เชธเช‚เช—เซเชฐเชนเชฟเชค เช•เชฐเชคเชพ เชจเชฅเซ€, เชชเชฐเช‚เชคเซ เชœเซเชฏเชพเช‚ เช—เชฃเชคเชฐเซ€เช“ เชฅเชพเชฏ เช›เซ‡.

เชฎเชนเชคเซเชตเชจเซ‹ เชฎเซเชฆเซเชฆเซ‹. เชคเซเชฐเซ€เชœเชพ เชชเซเชฐเช•เชพเชฐเชจเชพ เชจเซ‹เชกเซเชธเชจเซ‡ เช•เชพเชฐเชฃเซ‡ เช‘เชŸเซ‹เชธเซเช•เซ‡เชฒเชฟเช‚เช— เชฅเชถเซ‡. เชœเซ‹ เชคเชฎเซ‡ เชฌเซ€เชœเชพ เชชเซเชฐเช•เชพเชฐเชจเชพ เชจเซ‹เชกเซเชธ เชฒเซ‡เชตเชพเชจเซเช‚ เช…เชจเซ‡ เช‰เชฎเซ‡เชฐเชตเชพเชจเซเช‚ เชถเชฐเซ‚ เช•เชฐเซ‹ เช›เซ‹, เชคเซ‹ เชชเซเชฐเชคเชฟเชธเชพเชฆเชจเซ€ เชเชกเชช เช˜เชฃเซ€ เช“เช›เซ€ เชนเชถเซ‡ - เชกเชฟเช•เชฎเชฟเชถเชจเชฟเช‚เช— เช…เชจเซ‡ เชฐเชฟเช•เชฎเชฟเชŸเชฟเช‚เช— เชคเชฎเชพเชฐเชพ เช•เซเชฒเชธเซเชŸเชฐ เชชเชฐ เช•เชฒเชพเช•เซ‹ เชฒเซ‡เชถเซ‡. เช†, เช…เชฒเชฌเชคเซเชค, เชคเชฎเซ‡ เช“เชŸเซ‹เชธเซเช•เซ‡เชฒเชฟเช‚เช—เชฅเซ€ เช…เชชเซ‡เช•เซเชทเชพ เชฐเชพเช–เชคเชพ เชจเชฅเซ€. เชเชŸเชฒเซ‡ เช•เซ‡, เช…เชฎเซ‡ เชชเซเชฐเชฅเชฎ เช…เชจเซ‡ เชฌเซ€เชœเชพ เชชเซเชฐเช•เชพเชฐเชจเชพเช‚ เช—เชพเช‚เช เซ‹เชจเซ‡ เชธเซเชชเชฐเซเชถเชคเชพ เชจเชฅเซ€. เชคเซ‡เช“ เชจเซเชฏเซ‚เชจเชคเชฎ เชตเซเชฏเชตเชนเชพเชฐเซ เช•เซเชฒเชธเซเชŸเชฐเชจเซเช‚ เชชเซเชฐเชคเชฟเชจเชฟเชงเชฟเชคเซเชต เช•เชฐเชถเซ‡ เชœเซ‡ เชชเซเชฐเซ‹เช—เซเชฐเชพเชฎเชจเชพ เชธเชฎเช—เซเชฐ เชธเชฎเชฏเช—เชพเชณเชพ เชฆเชฐเชฎเชฟเชฏเชพเชจ เช…เชธเซเชคเชฟเชคเซเชตเชฎเชพเช‚ เชฐเชนเซ‡เชถเซ‡.

เชคเซ‡เชฅเซ€, เช…เชฎเชพเชฐเซเช‚ เช“เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐ Python 3 เชฎเชพเช‚ เชฒเช–เชพเชฏเซ‡เชฒเซเช‚ เช›เซ‡, เช•เซเชฒเชธเซเชŸเชฐ เชธเซ‡เชตเชพเช“เชจเซเช‚ เชธเช‚เชšเชพเชฒเชจ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ Ambari API เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ‡ เช›เซ‡, Mail.ru เช•เซเชฒเชพเช‰เชก เชธเซ‹เชฒเซเชฏเซเชถเชจเซเชธเชฎเชพเช‚เชฅเซ€ API (MCS) เชฎเชถเซ€เชจเซ‹ เชถเชฐเซ‚ เช•เชฐเชตเชพ เช…เชจเซ‡ เชฌเช‚เชง เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡.

เชธเซ‹เชฒเซเชฏเซเชถเชจ เช†เชฐเซเช•เชฟเชŸเซ‡เช•เซเชšเชฐ

  1. เชฎเซ‹เชกเซเชฏเซเชฒ autoscaler.py. เชคเซ‡เชฎเชพเช‚ เชคเซเชฐเชฃ เชตเชฐเซเช—เซ‹ เช›เซ‡: 1) เช…เช‚เชฌเชฐเซ€ เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡เชจเชพ เช•เชพเชฐเซเชฏเซ‹, 2) MCS เชธเชพเชฅเซ‡ เช•เชพเชฎ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡เชจเชพ เช•เชพเชฐเซเชฏเซ‹, 3) เช‘เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐเชจเชพ เชคเชฐเซเช• เชธเชพเชฅเซ‡ เชธเซ€เชงเชพ เชธเช‚เชฌเช‚เชงเชฟเชค เช•เชพเชฐเซเชฏเซ‹.
  2. เชธเซเช•เซเชฐเชฟเชชเซเชŸ observer.py. เช…เชจเชฟเชตเชพเชฐเซเชฏเชชเชฃเซ‡ เชคเซ‡ เชตเชฟเชตเชฟเชง เชจเชฟเชฏเชฎเซ‹ เชงเชฐเชพเชตเซ‡ เช›เซ‡: เช•เซเชฏเชพเชฐเซ‡ เช…เชจเซ‡ เช•เชˆ เช•เซเชทเชฃเซ‡ เช‘เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐ เชซเช‚เช•เซเชถเชจเชจเซ‡ เช•เซ‰เชฒ เช•เชฐเชตเซ‹.
  3. เชฐเซ‚เชชเชฐเซ‡เช–เชพเช‚เช•เชจ เชซเชพเช‡เชฒ config.py. เชคเซ‡เชฎเชพเช‚, เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เช“เชŸเซ‹เชธเซเช•เซ‡เชฒเชฟเช‚เช— เชฎเชพเชŸเซ‡ เชฎเชพเชจเซเชฏ เชจเซ‹เชกเซเชธเชจเซ€ เชธเซ‚เชšเชฟ เช…เชจเซ‡ เช…เชจเซเชฏ เชชเชฐเชฟเชฎเชพเชฃเซ‹ เช›เซ‡ เชœเซ‡ เช…เชธเชฐ เช•เชฐเซ‡ เช›เซ‡, เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เชจเชตเซ‹ เชจเซ‹เชก เช‰เชฎเซ‡เชฐเชตเชพเชจเซ€ เช•เซเชทเชฃเชฅเซ€ เช•เซ‡เชŸเชฒเซ‹ เชธเชฎเชฏ เชฐเชพเชน เชœเซ‹เชตเซ€. เชตเชฐเซเช—เซ‹ เชถเชฐเซ‚ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชŸเชพเช‡เชฎเชธเซเชŸเซ‡เชฎเซเชชเซเชธ เชชเชฃ เช›เซ‡, เชœเซ‡เชฅเซ€ เชตเชฐเซเช— เชชเชนเซ‡เชฒเชพเช‚ เชฎเชนเชคเซเชคเชฎ เช…เชจเซเชฎเชคเชฟ เชชเซเชฐเชพเชชเซเชค เช•เซเชฒเชธเซเชŸเชฐ เช—เซ‹เช เชตเชฃเซ€ เชถเชฐเซ‚ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡.

เชšเชพเชฒเซ‹ เชนเชตเซ‡ เชชเซเชฐเชฅเชฎ เชฌเซ‡ เชซเชพเชˆเชฒเซ‹เชจเซ€ เช…เช‚เชฆเชฐเชจเชพ เช•เซ‹เชกเชจเชพ เชŸเซเช•เชกเชพเช“ เชœเซ‹เชˆเช.

1. Autoscaler.py เชฎเซ‹เชกเซเชฏเซเชฒ

เช…เช‚เชฌเชฐเซ€ เชตเชฐเซเช—

เชตเชฐเซเช— เชธเชฎเชพเชตเชฟเชทเซเชŸ เช•เซ‹เชกเชจเซ‹ เชญเชพเช— เช† เชœเซ‡เชตเซ‹ เชฆเซ‡เช–เชพเชฏ เช›เซ‡ Ambari:

class Ambari:
    def __init__(self, ambari_url, cluster_name, headers, auth):
        self.ambari_url = ambari_url
        self.cluster_name = cluster_name
        self.headers = headers
        self.auth = auth

    def stop_all_services(self, hostname):
        url = self.ambari_url + self.cluster_name + '/hosts/' + hostname + '/host_components/'
        url2 = self.ambari_url + self.cluster_name + '/hosts/' + hostname
        req0 = requests.get(url2, headers=self.headers, auth=self.auth)
        services = req0.json()['host_components']
        services_list = list(map(lambda x: x['HostRoles']['component_name'], services))
        data = {
            "RequestInfo": {
                "context":"Stop All Host Components",
                "operation_level": {
                    "level":"HOST",
                    "cluster_name": self.cluster_name,
                    "host_names": hostname
                },
                "query":"HostRoles/component_name.in({0})".format(",".join(services_list))
            },
            "Body": {
                "HostRoles": {
                    "state":"INSTALLED"
                }
            }
        }
        req = requests.put(url, data=json.dumps(data), headers=self.headers, auth=self.auth)
        if req.status_code in [200, 201, 202]:
            message = 'Request accepted'
        else:
            message = req.status_code
        return message

เช‰เชชเชฐ, เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เชคเชฎเซ‡ เช•เชพเชฐเซเชฏเชจเชพ เช…เชฎเชฒเซ€เช•เชฐเชฃเชจเซ‡ เชœเซ‹เชˆ เชถเช•เซ‹ เช›เซ‹ stop_all_services, เชœเซ‡ เช‡เชšเซเช›เชฟเชค เช•เซเชฒเชธเซเชŸเชฐ เชจเซ‹เชก เชชเชฐ เชคเชฎเชพเชฎ เชธเซ‡เชตเชพเช“เชจเซ‡ เช…เชŸเช•เชพเชตเซ‡ เช›เซ‡.

เชตเชฐเซเช—เชจเชพ เชชเซเชฐเชตเซ‡เชถเชฆเซเชตเชพเชฐ เชชเชฐ Ambari เชคเชฎเซ‡ เชชเชพเชธ เช•เชฐเซ‹:

  • ambari_url, เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เชœเซ‡เชฎ 'http://localhost:8080/api/v1/clusters/',
  • cluster_name - เช…เช‚เชฌเชฐเซ€เชฎเชพเช‚ เชคเชฎเชพเชฐเชพ เช•เซเชฒเชธเซเชŸเชฐเชจเซเช‚ เชจเชพเชฎ,
  • headers = {'X-Requested-By': 'ambari'}
  • เช…เชจเซ‡ เช…เช‚เชฆเชฐ auth เช…เช‚เชฌเชฐเซ€ เชฎเชพเชŸเซ‡ เชคเชฎเชพเชฐเซเช‚ เชฒเซ‹เช—เชฟเชจ เช…เชจเซ‡ เชชเชพเชธเชตเชฐเซเชก เช† เชฐเชนเซเชฏเซ‹: auth = ('login', 'password').

เชซเช‚เช•เซเชถเชจ เชชเซ‹เชคเซ‡ REST API เชฆเซเชตเชพเชฐเชพ เช…เช‚เชฌเชฐเซ€ เชชเชฐเชจเชพ เชฌเซ‡ เช•เซ‹เชฒเซเชธ เชธเชฟเชตเชพเชฏ เชฌเซ€เชœเซเช‚ เช•เช‚เชˆ เชจเชฅเซ€. เชคเชพเชฐเซเช•เชฟเช• เชฆเซƒเชทเซเชŸเชฟเช•เซ‹เชฃเชฅเซ€, เช…เชฎเซ‡ เชชเซเชฐเชฅเชฎ เชจเซ‹เชก เชชเชฐ เชšเชพเชฒเซ€ เชฐเชนเซ‡เชฒเซ€ เชธเซ‡เชตเชพเช“เชจเซ€ เชธเซ‚เชšเชฟ เชชเซเชฐเชพเชชเซเชค เช•เชฐเซ€เช เช›เซ€เช, เช…เชจเซ‡ เชชเช›เซ€ เช†เชชเซ‡เชฒ เช•เซเชฒเชธเซเชŸเชฐ เชชเชฐ, เช†เชชเซ‡เชฒ เชจเซ‹เชก เชชเชฐ, เชธเซ‡เชตเชพเช“เชจเซ‡ เชธเซ‚เชšเชฟเชฎเชพเช‚เชฅเซ€ เชฐเชพเชœเซเชฏเชฎเชพเช‚ เชธเซเชฅเชพเชจเชพเช‚เชคเชฐเชฟเชค เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เช•เชนเซ€เช เช›เซ€เช. INSTALLED. เชคเชฎเชพเชฎ เชธเซ‡เชตเชพเช“ เชถเชฐเซ‚ เช•เชฐเชตเชพ, เชฐเชพเชœเซเชฏเชฎเชพเช‚ เชจเซ‹เชกเซเชธ เชŸเซเชฐเชพเชจเซเชธเชซเชฐ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡เชจเชพ เช•เชพเชฐเซเชฏเซ‹ Maintenance เชตเช—เซ‡เชฐเซ‡ เชธเชฎเชพเชจ เชฆเซ‡เช–เชพเชฏ เช›เซ‡ - เชคเซ‡ API เชฆเซเชตเชพเชฐเชพ เชฎเชพเชคเซเชฐ เชฅเซ‹เชกเซ€ เชตเชฟเชจเช‚เชคเซ€เช“ เช›เซ‡.

เชตเชฐเซเช— Mcs

เชตเชฐเซเช— เชธเชฎเชพเชตเชฟเชทเซเชŸ เช•เซ‹เชกเชจเซ‹ เชญเชพเช— เช† เชœเซ‡เชตเซ‹ เชฆเซ‡เช–เชพเชฏ เช›เซ‡ Mcs:

class Mcs:
    def __init__(self, id1, id2, password):
        self.id1 = id1
        self.id2 = id2
        self.password = password
        self.mcs_host = 'https://infra.mail.ru:8774/v2.1'

    def vm_turn_on(self, hostname):
        self.token = self.get_mcs_token()
        host = self.hostname_to_vmname(hostname)
        vm_id = self.get_vm_id(host)
        mcs_url1 = self.mcs_host + '/servers/' + self.vm_id + '/action'
        headers = {
            'X-Auth-Token': '{0}'.format(self.token),
            'Content-Type': 'application/json'
        }
        data = {'os-start' : 'null'}
        mcs = requests.post(mcs_url1, data=json.dumps(data), headers=headers)
        return mcs.status_code

เชตเชฐเซเช—เชจเชพ เชชเซเชฐเชตเซ‡เชถเชฆเซเชตเชพเชฐ เชชเชฐ Mcs เช…เชฎเซ‡ เช•เซเชฒเชพเช‰เชกเชจเซ€ เช…เช‚เชฆเชฐ เชชเซเชฐเซ‹เชœเซ‡เช•เซเชŸ เช†เชˆเชกเซ€ เช…เชจเซ‡ เชฏเซเชเชฐ เช†เชˆเชกเซ€ เชคเซ‡เชฎเชœ เชคเซ‡เชจเซ‹ เชชเชพเชธเชตเชฐเซเชก เชชเชพเชธ เช•เชฐเซ€เช เช›เซ€เช. เช•เชพเชฐเซเชฏเชฎเชพเช‚ vm_turn_on เช…เชฎเซ‡ เชเช• เชฎเชถเซ€เชจ เชšเชพเชฒเซ เช•เชฐเชตเชพ เชฎเชพเช‚เช—เซ€เช เช›เซ€เช. เช…เชนเซ€เช‚เชจเซ‹ เชคเชฐเซเช• เชฅเซ‹เชกเซ‹ เชตเชงเซ เชœเชŸเชฟเชฒ เช›เซ‡. เช•เซ‹เชกเชจเซ€ เชถเชฐเซ‚เช†เชคเชฎเชพเช‚, เช…เชจเซเชฏ เชคเซเชฐเชฃ เชซเช‚เช•เซเชถเชจ เช•เชนเซ‡เชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡: 1) เช†เชชเชฃเซ‡ เชŸเซ‹เช•เชจ เชฎเซ‡เชณเชตเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡, 2) เช†เชชเชฃเซ‡ เชนเซ‹เชธเซเชŸเชจเซ‡เชฎเชจเซ‡ MCS เชฎเชพเช‚ เชฎเชถเซ€เชจเชจเชพ เชจเชพเชฎเชฎเชพเช‚ เช•เชจเซเชตเชฐเซเชŸ เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡, 3) เช† เชฎเชถเซ€เชจเชจเซ€ เช†เชˆเชกเซ€ เชฎเซ‡เชณเชตเซ‹. เช†เช—เชณ, เช…เชฎเซ‡ เช–เชพเชฒเซ€ เชชเซ‹เชธเซเชŸ เชตเชฟเชจเช‚เชคเซ€ เช•เชฐเซ€เช เช›เซ€เช เช…เชจเซ‡ เช† เชฎเชถเซ€เชจเชจเซ‡ เชฒเซ‹เชจเซเชš เช•เชฐเซ€เช เช›เซ€เช.

เชŸเซ‹เช•เชจ เชฎเซ‡เชณเชตเชตเชพเชจเซเช‚ เช•เชพเชฐเซเชฏ เช†เชจเชพ เชœเซ‡เชตเซเช‚ เชฆเซ‡เช–เชพเชฏ เช›เซ‡:

def get_mcs_token(self):
        url = 'https://infra.mail.ru:35357/v3/auth/tokens?nocatalog'
        headers = {'Content-Type': 'application/json'}
        data = {
            'auth': {
                'identity': {
                    'methods': ['password'],
                    'password': {
                        'user': {
                            'id': self.id1,
                            'password': self.password
                        }
                    }
                },
                'scope': {
                    'project': {
                        'id': self.id2
                    }
                }
            }
        }
        params = (('nocatalog', ''),)
        req = requests.post(url, data=json.dumps(data), headers=headers, params=params)
        self.token = req.headers['X-Subject-Token']
        return self.token

เช“เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐ เชตเชฐเซเช—

เช† เชตเชฐเซเช—เชฎเชพเช‚ เช“เชชเชฐเซ‡เชŸเชฟเช‚เช— เชคเชฐเซเช• เชธเชพเชฅเซ‡ เชธเช‚เชฌเช‚เชงเชฟเชค เช•เชพเชฐเซเชฏเซ‹ เช›เซ‡.

เช† เชตเชฐเซเช— เชฎเชพเชŸเซ‡ เช•เซ‹เชกเชจเซ‹ เชญเชพเช— เช†เชจเชพ เชœเซ‡เชตเซ‹ เชฆเซ‡เช–เชพเชฏ เช›เซ‡:

class Autoscaler:
    def __init__(self, ambari, mcs, scaling_hosts, yarn_ram_per_node, yarn_cpu_per_node):
        self.scaling_hosts = scaling_hosts
        self.ambari = ambari
        self.mcs = mcs
        self.q_ram = deque()
        self.q_cpu = deque()
        self.num = 0
        self.yarn_ram_per_node = yarn_ram_per_node
        self.yarn_cpu_per_node = yarn_cpu_per_node

    def scale_down(self, hostname):
        flag1 = flag2 = flag3 = flag4 = flag5 = False
        if hostname in self.scaling_hosts:
            while True:
                time.sleep(5)
                status1 = self.ambari.decommission_nodemanager(hostname)
                if status1 == 'Request accepted' or status1 == 500:
                    flag1 = True
                    logging.info('Decomission request accepted: {0}'.format(flag1))
                    break
            while True:
                time.sleep(5)
                status3 = self.ambari.check_service(hostname, 'NODEMANAGER')
                if status3 == 'INSTALLED':
                    flag3 = True
                    logging.info('Nodemaneger decommissioned: {0}'.format(flag3))
                    break
            while True:
                time.sleep(5)
                status2 = self.ambari.maintenance_on(hostname)
                if status2 == 'Request accepted' or status2 == 500:
                    flag2 = True
                    logging.info('Maintenance request accepted: {0}'.format(flag2))
                    break
            while True:
                time.sleep(5)
                status4 = self.ambari.check_maintenance(hostname, 'NODEMANAGER')
                if status4 == 'ON' or status4 == 'IMPLIED_FROM_HOST':
                    flag4 = True
                    self.ambari.stop_all_services(hostname)
                    logging.info('Maintenance is on: {0}'.format(flag4))
                    logging.info('Stopping services')
                    break
            time.sleep(90)
            status5 = self.mcs.vm_turn_off(hostname)
            while True:
                time.sleep(5)
                status5 = self.mcs.get_vm_info(hostname)['server']['status']
                if status5 == 'SHUTOFF':
                    flag5 = True
                    logging.info('VM is turned off: {0}'.format(flag5))
                    break
            if flag1 and flag2 and flag3 and flag4 and flag5:
                message = 'Success'
                logging.info('Scale-down finished')
                logging.info('Cooldown period has started. Wait for several minutes')
        return message

เช…เชฎเซ‡ เชชเซเชฐเชตเซ‡เชถ เชฎเชพเชŸเซ‡ เชตเชฐเซเช—เซ‹ เชธเซเชตเซ€เช•เชพเชฐเซ€เช เช›เซ€เช. Ambari ะธ Mcs, เชจเซ‹เชกเซเชธเชจเซ€ เชธเซ‚เชšเชฟ เช•เซ‡ เชœเซ‡ เชธเซเช•เซ‡เชฒเชฟเช‚เช— เชฎเชพเชŸเซ‡ เชฎเชพเชจเซเชฏ เช›เซ‡, เชคเซ‡เชฎเชœ เชจเซ‹เชก เชฐเซ‚เชชเชฐเซ‡เช–เชพเช‚เช•เชจ เชชเชฐเชฟเชฎเชพเชฃเซ‹: เชฎเซ‡เชฎเชฐเซ€ เช…เชจเซ‡ เชธเซ€เชชเซ€เชฏเซ เชฏเชพเชฐเซเชจเชฎเชพเช‚ เชจเซ‹เชกเชจเซ‡ เชซเชพเชณเชตเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡. เชคเซเชฏเชพเช‚ เชชเชฃ 2 เช†เช‚เชคเชฐเชฟเช• เชชเชฐเชฟเชฎเชพเชฃเซ‹ q_ram, q_cpu เช›เซ‡, เชœเซ‡ เช•เชคเชพเชฐ เช›เซ‡. เชคเซ‡เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡, เช…เชฎเซ‡ เชตเชฐเซเชคเชฎเชพเชจ เช•เซเชฒเชธเซเชŸเชฐ เชฒเซ‹เชกเชจเชพ เชฎเซ‚เชฒเซเชฏเซ‹เชจเซ‡ เชธเช‚เช—เซเชฐเชนเชฟเชค เช•เชฐเซ€เช เช›เซ€เช. เชœเซ‹ เช†เชชเชฃเซ‡ เชœเซ‹เชˆเช เช•เซ‡ เช›เซ‡เชฒเซเชฒเซ€ 5 เชฎเชฟเชจเชฟเชŸเชฎเชพเช‚ เชฒเซ‹เชกเชฎเชพเช‚ เชธเชคเชค เชตเชงเชพเชฐเซ‹ เชฅเชฏเซ‹ เช›เซ‡, เชคเซ‹ เช…เชฎเซ‡ เชจเช•เซเช•เซ€ เช•เชฐเซ€เช เช›เซ€เช เช•เซ‡ เช†เชชเชฃเซ‡ เช•เซเชฒเชธเซเชŸเชฐเชฎเชพเช‚ +1 เชจเซ‹เชก เช‰เชฎเซ‡เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡. เช•เซเชฒเชธเซเชŸเชฐ เช…เช‚เชกเชฐเชฏเซเชŸเชฟเชฒเชพเชˆเชเซ‡เชถเชจ เชธเซเชŸเซ‡เชŸ เชฎเชพเชŸเซ‡ เชชเชฃ เช†เชตเซเช‚ เชœ เช›เซ‡.

เช‰เชชเชฐเชจเซ‹ เช•เซ‹เชก เช เชซเช‚เช•เซเชถเชจเชจเซเช‚ เช‰เชฆเชพเชนเชฐเชฃ เช›เซ‡ เชœเซ‡ เช•เซเชฒเชธเซเชŸเชฐเชฎเชพเช‚เชฅเซ€ เชฎเชถเซ€เชจเชจเซ‡ เชฆเซ‚เชฐ เช•เชฐเซ‡ เช›เซ‡ เช…เชจเซ‡ เชคเซ‡เชจเซ‡ เช•เซเชฒเชพเช‰เชกเชฎเชพเช‚ เชฐเซ‹เช•เซ‡ เช›เซ‡. เชชเซเชฐเชฅเชฎ เชคเซเชฏเชพเช‚ เชกเชฟเช•เชฎเชฟเชถเชจเชฟเช‚เช— เช›เซ‡ YARN Nodemanager, เชชเช›เซ€ เชฎเซ‹เชก เชšเชพเชฒเซ เชฅเชพเชฏ เช›เซ‡ Maintenance, เชชเช›เซ€ เช…เชฎเซ‡ เชฎเชถเซ€เชจ เชชเชฐเชจเซ€ เชฌเชงเซ€ เชธเซ‡เชตเชพเช“ เชฌเช‚เชง เช•เชฐเซ€เช เช›เซ€เช เช…เชจเซ‡ เช•เซเชฒเชพเช‰เชกเชฎเชพเช‚ เชตเชฐเซเชšเซเชฏเซเช…เชฒ เชฎเชถเซ€เชจ เชฌเช‚เชง เช•เชฐเซ€เช เช›เซ€เช.

2. เชธเซเช•เซเชฐเชฟเชชเซเชŸ เชจเชฟเชฐเซ€เช•เซเชทเช•.py

เชคเซเชฏเชพเช‚เชฅเซ€ เชจเชฎเซ‚เชจเชพ เช•เซ‹เชก:

if scaler.assert_up(config.scale_up_thresholds) == True:
        hostname = cloud.get_vm_to_up(config.scaling_hosts)
        if hostname != None:
            status1 = scaler.scale_up(hostname)
            if status1 == 'Success':
                text = {"text": "{0} has been successfully scaled-up".format(hostname)}
                post = {"text": "{0}".format(text)}
                json_data = json.dumps(post)
                req = requests.post(webhook, data=json_data.encode('ascii'), headers={'Content-Type': 'application/json'})
                time.sleep(config.cooldown_period*60)

เชคเซ‡เชฎเชพเช‚, เช…เชฎเซ‡ เชคเชชเชพเชธ เช•เชฐเซ€เช เช›เซ€เช เช•เซ‡ เช•เซเชฒเชธเซเชŸเชฐเชจเซ€ เช•เซเชทเชฎเชคเชพ เชตเชงเชพเชฐเชตเชพ เชฎเชพเชŸเซ‡ เชชเชฐเชฟเชธเซเชฅเชฟเชคเชฟเช“ เชตเชฟเช•เชธเชฟเชค เชฅเชˆ เช›เซ‡ เช•เซ‡ เช•เซ‡เชฎ เช…เชจเซ‡ เช…เชจเชพเชฎเชคเชฎเชพเช‚ เช•เซ‹เชˆ เชฎเชถเซ€เชจ เช›เซ‡ เช•เซ‡ เช•เซ‡เชฎ, เชคเซ‡เชฎเชพเช‚เชฅเซ€ เชเช•เชจเซเช‚ เชนเซ‹เชธเซเชŸเชจเชพเชฎ เชฎเซ‡เชณเชตเซ€เช เช›เซ€เช, เชคเซ‡เชจเซ‡ เช•เซเชฒเชธเซเชŸเชฐเชฎเชพเช‚ เช‰เชฎเซ‡เชฐเซ€เช เช›เซ€เช เช…เชจเซ‡ เช…เชฎเชพเชฐเซ€ เชŸเซ€เชฎเชจเชพ เชธเซเชฒเซ‡เช• เชชเชฐ เชคเซ‡เชจเชพ เชตเชฟเชถเซ‡ เชธเช‚เชฆเซ‡เชถ เชชเซเชฐเช•เชพเชถเชฟเชค เช•เชฐเซ€เช เช›เซ€เช. เชœเซ‡ เชชเช›เซ€ เชคเซ‡ เชถเชฐเซ‚ เชฅเชพเชฏ เช›เซ‡ cooldown_period, เชœเซเชฏเชพเชฐเซ‡ เช…เชฎเซ‡ เช•เซเชฒเชธเซเชŸเชฐเชฎเชพเช‚เชฅเซ€ เช•เช‚เชˆเชชเชฃ เช‰เชฎเซ‡เชฐเชคเชพ เชจเชฅเซ€ เช…เชฅเชตเชพ เชฆเซ‚เชฐ เช•เชฐเชคเชพ เชจเชฅเซ€, เชชเชฐเช‚เชคเซ เชซเช•เซเชค เชฒเซ‹เชกเชจเซเช‚ เชจเชฟเชฐเซ€เช•เซเชทเชฃ เช•เชฐเซ€เช เช›เซ€เช. เชœเซ‹ เชคเซ‡ เชธเซเชฅเชฟเชฐ เชฅเชˆ เช—เชฏเซเช‚ เช›เซ‡ เช…เชจเซ‡ เชถเซเชฐเซ‡เชทเซเช  เชฒเซ‹เชก เชฎเซ‚เชฒเซเชฏเซ‹เชจเชพ เช•เซ‹เชฐเชฟเชกเซ‹เชฐเชฎเชพเช‚ เช›เซ‡, เชคเซ‹ เช…เชฎเซ‡ เชซเช•เซเชค เชฆเซ‡เช–เชฐเซ‡เช– เชšเชพเชฒเซ เชฐเชพเช–เซ€เช เช›เซ€เช. เชœเซ‹ เชเช• เชจเซ‹เชก เชชเซ‚เชฐเชคเซ‹ เชจ เชนเชคเซ‹, เชคเซ‹ เช…เชฎเซ‡ เชฌเซ€เชœเซ‹ เช‰เชฎเซ‡เชฐเซ‹.

เชเชตเชพ เช•เชฟเชธเซเชธเชพเช“ เชฎเชพเชŸเซ‡ เชœเซเชฏเชพเชฐเซ‡ เช…เชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ เชชเชพเช  เช†เช—เชณ เชนเซ‹เชฏ, เช…เชฎเซ‡ เชชเชนเซ‡เชฒเชพเชฅเซ€ เชœ เช–เชพเชคเชฐเซ€เชชเซ‚เชฐเซเชตเช• เชœเชพเชฃเซ€เช เช›เซ€เช เช•เซ‡ เชเช• เชจเซ‹เชก เชชเซ‚เชฐเชคเซ‹ เชจเชฅเซ€, เชคเซ‡เชฅเซ€ เช…เชฎเซ‡ เชคเชฐเชค เชœ เชคเชฎเชพเชฎ เชฎเชซเชค เช—เชพเช‚เช เซ‹ เชถเชฐเซ‚ เช•เชฐเซ€เช เช›เซ€เช เช…เชจเซ‡ เชชเชพเช เชจเชพ เช…เช‚เชค เชธเซเชงเซ€ เชคเซ‡เชฎเชจเซ‡ เชธเช•เซเชฐเชฟเชฏ เชฐเชพเช–เซ€เช เช›เซ€เช. เช† เชชเซเชฐเชตเซƒเชคเซเชคเชฟ เชŸเชพเช‡เชฎเชธเซเชŸเซ‡เชฎเซเชชเซเชธเชจเซ€ เชธเซ‚เชšเชฟเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชฅเชพเชฏ เช›เซ‡.

เชจเชฟเชทเซเช•เชฐเซเชท

เชœเซเชฏเชพเชฐเซ‡ เชคเชฎเซ‡ เช…เชธเชฎเชพเชจ เช•เซเชฒเชธเซเชŸเชฐ เชฒเซ‹เชกเชฟเช‚เช—เชจเซ‹ เช…เชจเซเชญเชต เช•เชฐเซ‹ เช›เซ‹ เชคเซเชฏเชพเชฐเซ‡ เชคเซ‡ เช•เซ‡เชธ เชฎเชพเชŸเซ‡ เช‘เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐ เช เชธเชพเชฐเซ‹ เช…เชจเซ‡ เช…เชจเซเช•เซ‚เชณ เช‰เช•เซ‡เชฒ เช›เซ‡. เชคเชฎเซ‡ เชเช•เชธเชพเชฅเซ‡ เชชเซ€เช• เชฒเซ‹เชก เชฎเชพเชŸเซ‡ เช‡เชšเซเช›เชฟเชค เช•เซเชฒเชธเซเชŸเชฐ เช—เซ‹เช เชตเชฃเซ€ เชนเชพเช‚เชธเชฒ เช•เชฐเซ‹ เช›เซ‹ เช…เชจเซ‡ เชคเซ‡ เชœ เชธเชฎเชฏเซ‡ เช† เช•เซเชฒเชธเซเชŸเชฐเชจเซ‡ เช…เช‚เชกเชฐเชฒเซ‹เชก เชฆเชฐเชฎเชฟเชฏเชพเชจ เชฐเชพเช–เชถเซ‹ เชจเชนเซ€เช‚, เชชเซˆเชธเชพเชจเซ€ เชฌเชšเชค เช•เชฐเซ‹. เชธเชพเชฐเซเช‚, เชตเชคเซเชคเชพ เช† เชฌเชงเซเช‚ เชคเชฎเชพเชฐเซ€ เชธเชนเชญเชพเช—เชฟเชคเชพ เชตเชฟเชจเชพ เช†เชชเชฎเซ‡เชณเซ‡ เชฅเชพเชฏ เช›เซ‡. เช‘เชŸเซ‹เชธเซเช•เซ‡เชฒเชฐ เชชเซ‹เชคเซ‡ เช•เซเชฒเชธเซเชŸเชฐ เชฎเซ‡เชจเซ‡เชœเชฐ API เช…เชจเซ‡ เช•เซเชฒเชพเช‰เชก เชชเซเชฐเชฆเชพเชคเชพ API เชจเซ‡ เชตเชฟเชจเช‚เชคเซ€เช“เชจเชพ เชธเชฎเซ‚เชน เชธเชฟเชตเชพเชฏ เชฌเซ€เชœเซเช‚ เช•เช‚เชˆ เชจเชฅเซ€, เชœเซ‡ เชšเซ‹เช•เซเช•เชธ เชคเชฐเซเช• เช…เชจเซเชธเชพเชฐ เชฒเช–เชพเชฏเซ‡เชฒ เช›เซ‡. เชคเชฎเชพเชฐเซ‡ เชœเซ‡ เชšเซ‹เช•เซเช•เชธเชชเชฃเซ‡ เชฏเชพเชฆ เชฐเชพเช–เชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡ เชคเซ‡ เช—เชพเช‚เช เซ‹เชจเซเช‚ 3 เชชเซเชฐเช•เชพเชฐเซ‹เชฎเชพเช‚ เชตเชฟเชญเชพเชœเชจ เช›เซ‡, เชœเซ‡เชฎ เช†เชชเชฃเซ‡ เช…เช—เชพเช‰ เชฒเช–เซเชฏเซเช‚ เชนเชคเซเช‚. เช…เชจเซ‡ เชคเชฎเซ‡ เช–เซเชถ เชฅเชถเซ‹.

เชธเซ‹เชฐเซเชธ: www.habr.com

เชเช• เชŸเชฟเชชเซเชชเชฃเซ€ เช‰เชฎเซ‡เชฐเซ‹