Простой диспетчер задач с веб-интерфейсом, написанный на языке GO для Unix-систем включая Android.

Когда я работал в одной фирме, которая занимается электронными гос-услугами, меня всегда удивляло, что системы, которые мы делали или модернизировали становятся со временем чрезвычайно сложными. Они становились рыхлыми и ненадежными с огромным количеством зависимостей. Подобно красному гиганту, система раздувалась и в любой момент могла сколапсировать.
Развитие систем — не только наращивание функционала, но еще и сокращение и оптимизация систем.
Как мне кажется, в it-сфере происходит то же самое. Взгляните на Windows 8.1, это же жертва идей маркетологов. Помните Torrent-клиент Azureus? Теперь это уже целый медиа-комбайн Vuze.
Мне всегда хотелось написать программу для себя. Что-нибудь простое и не сложное, работающее через веб-интерфес, что-то вроде диспетчера задач top, только работающее через браузер. Очень много систем которые могут выполнять подобного рода функционал, но они из серии:
Поставь PHP + Apache+ MySQL+… еще что-нибудь. Т.е. на мой взгляд излишне «раздутые».
Когда я выбирал язык, я обратил свое внимание на GO. На «хабре» в последнее время очень много о нем заслуженно пишут.
Как только я начал читать книги и статьи о нем, сразу влюбился в этот потрясающий лаконичный и естественный язык. Меня поражало то, на сколько, мнение создателей совпадало с моим
Вот примеры:
Для получения сведения о процессах и статистике системы wtop использует виртуальную файловую систему proc. Поэтому он будет работать на любой системе, которая ее использует(включая android и… я не уверен Plan9). В качестве backend используется встроенный в go http-server. А в качестве frontend html/java script. Для обмена данными между frontenf и backend используется json-сообщения. Для запуска достаточно запустить исполняемый файл и в браузере перейти по адресу x.x.x.x:9977/index.html


На скриншоте выше видно, что в момент сбора сведений, на телефоне с двухъядерным процессором Texas Instruments 4430, частотой 1.2 ГГц, wtop потребляет около 10% процентов процессорного времени и всего 4,5 мегабайта памяти, что немного. На десктопе, с операционной системой ubuntu — 0,5% процессорного времени и те же 4.5 мегабайта памяти. Если в течении 5 секунд не было запроса от клиента, то он засыпает до тех пор, пока новый json-запрос его не разбудит.
Далее опишу, какие конструкции основные моменты используются в коде программы.
При получении объекта http.Request, метод ProduceJsonRequest «парсит» тело запроса и создает объект запроса. Который в свою очередь диспечеризуется методом Dispatch:
При диспечеризации запроса происходит поиск по словарю, соответствующего обработчика, с последующим его вызовом.
В обработке запроса ничего интересного нету.
Интерес предоставляет структура BatchJob. Используя ее в своем объекте, мы можем обеспечить периодичность выполнения некоторых действий (в нашем случае измерений).
Для этого в каждом обработчике запроса присутствует объект структуры BatchJob. Поле Job мы инстанцируем ссылкой на функцию измерения.
Как я уже отмечал выше, если через 5 секунд сервис никто не опросит, то он уснет.
На мой взгляд, программа получилась очень простой и логичной. Каждый ее модуль выполняет конкретную функцию и может работать независимо друг от друга.
Все иcходные коды доступны на репозитарии GitHub github.com/Loafter/WebTop.
От себя хотелось бы еще раз сказать, что GO это удивительный и мощный язык. Надеюсь он займет доминирующую роль среди языков нового поколения.
Для тех, кто дочитал до конца, привожу ссылки на скомпилированные под разные архитектуры бинарники.
index.html — веб-интерфейс;
wtop-armv5-linux — версия для Linux (Android) arm v5;
wtop-armv6-linux — версия для Linux (Android) arm v6;
wtop-x64-linux — версия для Linux (Ubuntu… etc) X86-64.

Когда я работал в одной фирме, которая занимается электронными гос-услугами, меня всегда удивляло, что системы, которые мы делали или модернизировали становятся со временем чрезвычайно сложными. Они становились рыхлыми и ненадежными с огромным количеством зависимостей. Подобно красному гиганту, система раздувалась и в любой момент могла сколапсировать.
Развитие систем — не только наращивание функционала, но еще и сокращение и оптимизация систем.
Как мне кажется, в it-сфере происходит то же самое. Взгляните на Windows 8.1, это же жертва идей маркетологов. Помните Torrent-клиент Azureus? Теперь это уже целый медиа-комбайн Vuze.
Мне всегда хотелось написать программу для себя. Что-нибудь простое и не сложное, работающее через веб-интерфес, что-то вроде диспетчера задач top, только работающее через браузер. Очень много систем которые могут выполнять подобного рода функционал, но они из серии:
Поставь PHP + Apache+ MySQL+… еще что-нибудь. Т.е. на мой взгляд излишне «раздутые».
Когда я выбирал язык, я обратил свое внимание на GO. На «хабре» в последнее время очень много о нем заслуженно пишут.
Как только я начал читать книги и статьи о нем, сразу влюбился в этот потрясающий лаконичный и естественный язык. Меня поражало то, на сколько, мнение создателей совпадало с моим
Вот примеры:
- В нем нет шаблонов. Шаблоны это наследие макросов. Решая задачу обобщения алгоритмов и классов, использование шаблонов, на порядок усложняло понимание кода.
- В GO нет наследования. Как нет множественного наследования, так и нету обычного наследования. За место наследования используется более четкий и ясные механизмы встраивания и интерфейсы.
- По умолчанию компилируемый файл статически слинкован. Это означает, что его можно запустить на любой системе, не заботясь о зависимостях.
- Из коробки поддерживается кросскомпиляция.
- Есть Unit-тестирование.
Для получения сведения о процессах и статистике системы wtop использует виртуальную файловую систему proc. Поэтому он будет работать на любой системе, которая ее использует(включая android и… я не уверен Plan9). В качестве backend используется встроенный в go http-server. А в качестве frontend html/java script. Для обмена данными между frontenf и backend используется json-сообщения. Для запуска достаточно запустить исполняемый файл и в браузере перейти по адресу x.x.x.x:9977/index.html


На скриншоте выше видно, что в момент сбора сведений, на телефоне с двухъядерным процессором Texas Instruments 4430, частотой 1.2 ГГц, wtop потребляет около 10% процентов процессорного времени и всего 4,5 мегабайта памяти, что немного. На десктопе, с операционной системой ubuntu — 0,5% процессорного времени и те же 4.5 мегабайта памяти. Если в течении 5 секунд не было запроса от клиента, то он засыпает до тех пор, пока новый json-запрос его не разбудит.
Далее опишу, какие конструкции основные моменты используются в коде программы.
При получении объекта http.Request, метод ProduceJsonRequest «парсит» тело запроса и создает объект запроса. Который в свою очередь диспечеризуется методом Dispatch:
func (fabric *JsonFabric) ProduceJsonRequest(request *http.Request) (Request, error) { bodyData, err := ioutil.ReadAll(request.Body) if err != nil { stErr := "error: Can't read request body" log.Println(stErr) return nil, errors.New(stErr) } defer request.Body.Close() var basicRequest BasicRequest err = json.Unmarshal(bodyData, &basicRequest) if err != nil { stErr := "error: Can't parse basic data" log.Println(stErr) return nil, errors.New(stErr) } switch basicRequest.Type { case ServiceStatus: var serviceStateRequest ServiceStateRequest err := json.Unmarshal(bodyData, &serviceStateRequest) if err != nil { stErr := "error: Can't parse service state request" log.Println(stErr) return nil, errors.New("error: Can't parse service state request") } return serviceStateRequest, nil ...... ...... ...... } return nil, errors.New("error: Unknown request type")
func (requestSelector *RequestSelector) Dispatch(request Request, responseWriter http.ResponseWriter, httpRequest *http.Request) error { //don't need protect multiple read in different thread if selector, contains := requestSelector.selectorRequestMap[request.RequestType()]; !contains { stErr := "error: Usupported message type" log.Println(stErr) return errors.New(stErr) } else { return selector.Dispatch(request, responseWriter, httpRequest) } }
При диспечеризации запроса происходит поиск по словарю, соответствующего обработчика, с последующим его вызовом.
В обработке запроса ничего интересного нету.
Интерес предоставляет структура BatchJob. Используя ее в своем объекте, мы можем обеспечить периодичность выполнения некоторых действий (в нашем случае измерений).
type BatchJob struct { Job func() runJob bool done chan bool } func (batchJob *BatchJob) Start() error { if batchJob.runJob { return errors.New("error: can't stop not stopped job") } if batchJob.Job == nil { return errors.New("error: empty job function") } if !batchJob.runJob { batchJob.done = make(chan bool, 1) } go batchJob.execution(batchJob.done) batchJob.runJob = true return nil } func (batchJob *BatchJob) IsRunning() bool { return batchJob.runJob } func (batchJob *BatchJob) Stop() error { if !batchJob.runJob { return errors.New("error: can't stop not stopted job") } batchJob.runJob = false isDone := <-batchJob.done if isDone { close(batchJob.done) return nil } return errors.New("error: failed stop job") } func (batchJob *BatchJob) execution(done chan bool) { for { if batchJob.runJob { batchJob.Job() } else { done <- true return } } }
Для этого в каждом обработчике запроса присутствует объект структуры BatchJob. Поле Job мы инстанцируем ссылкой на функцию измерения.
top.collectInfoJob.Job = top.collectInfo top.lastRequestTime = time.Now() err := top.collectInfoJob.Start()
Как я уже отмечал выше, если через 5 секунд сервис никто не опросит, то он уснет.
На мой взгляд, программа получилась очень простой и логичной. Каждый ее модуль выполняет конкретную функцию и может работать независимо друг от друга.
Все иcходные коды доступны на репозитарии GitHub github.com/Loafter/WebTop.
От себя хотелось бы еще раз сказать, что GO это удивительный и мощный язык. Надеюсь он займет доминирующую роль среди языков нового поколения.
Для тех, кто дочитал до конца, привожу ссылки на скомпилированные под разные архитектуры бинарники.
index.html — веб-интерфейс;
wtop-armv5-linux — версия для Linux (Android) arm v5;
wtop-armv6-linux — версия для Linux (Android) arm v6;
wtop-x64-linux — версия для Linux (Ubuntu… etc) X86-64.
