Пользователь
0,0
рейтинг
9 октября 2012 в 15:18

Разработка → DBSlayer прокси на BASH за 5 минут или еще один способ отдать JSON из MySQL tutorial



Дело было вечером, делать было нечего, но дурная голова уркам покоя не давала… Данный пост создан как результат чисто-академического интереса. А началось все с того, что при разработке небольшого клиентского приложения для своих нужд, реализованного на Javascript, появилась необходимость взаимодействовать с уже существующей базой, где хранятся искомые данные. База — MySQL. Один из простых способов — реализация серверного скрипта (на PHP или еще каком языке), который по входящим параметрам делает нужный запрос и возвращает результат в JSON виде.

Другой вариант — это DBSlayer-прокси для MySQL. Кто про него не слышал, рассказываю в крадце: был создан в недрах New York Times как средство абстракции и балансирования нагрузки на БД. Подробнее можно почитать на сайте code.nytimes.com/projects/dbslayer/wiki/WhyUseIt. DBSlayer предоставляет API на основе JSON, известен в кругу NodeJS разработчиков.

Но это тоже не наш метод. Под катом приведено простое решение данной задачи на BASH.



Ну вот лень мне ставить было эту приблуду, да и задача, напомню, решается чисто для себя, никаких нагрузок и прочих радостей продакшн решений. Писать на PHP немного надоело, душа просила разнообразия и какого-нить выпендрежа. Решил сделать свою простую прослойку, в виде HTTP сервера на BASH, с реализацией нужного функционала.

Ни для кого не секрет, что Netcat в связке с дописыванием пары строк на баше можно превратить в WEB сервер. На хабре даже были посты про это. Взяв эту идею и доработав, мы можем получить простой аналог DBSlayer на коленке bash за пять минут.

От слов к действию...


Сначала напишем простую вспомогательную утилиту, для конвертирования вывода результатов из консольного клиента mysql в JSON формат:

cat ~/bin/mysql2json.sh
#!/bin/bash

sed -e 's/\t/\",\"/g' \
    -e 's/^/\[\"/'    \
    -e 's/$/\"\],/'   \
    -e '1s/\(.*\)/\{\"fields\":\1\ \"data\":[/g' -e '$s/.$/\]\}/' \
| tr -d "\n"


Используется она просто:
mysql -e "SELECT * FROM `mytable`" | ./mysql2json.sh

{"fields":["field_1","field_2","field_3"],"data":[["1","2","3"],["4","5","6"],["7","8","9"]]}


Теперь сам код сервера, который помещаем в файл dbjs.sh:
#!/bin/bash

:;while [ $? -eq 0 ]
do.
  nc -vlp 8880 -c '(
    r=read;
    e=echo;

    $r a b c;

    z=$r;

    while [ ${#z} -gt 2 ]
    do.
      $r z;
    done;

    f=`$e $b|sed 's/[^a-z0-9_.-]//gi'`;

    h="HTTP/1.0";
    o="$h 200 OK\r\n";
    c="Content";

    m="mysql -ulol -ptrololo"
    m2j="~/bin/mysql2json.sh"

    $e "$o$c-Type: text/json";
    $e;

    if [[ ( -n "$f" ) && ( "$f" != "favicon.ico" ) ]]
    then.
      $e "+ Connect to [$f]">&2;

      db=${f%.*};
      tb=${f#*.};

      if [ "$tb" = "$db" ]
      then
        $e `$m ${db:-test} -e "show tables" | $m2j`;
      else
        $e `$m ${db:-test} -e "select * from $tb" | $m2j`;
      fi;

    else
      $e `$m -e "show databases" | $m2j`;
    fi
  )';
done


Собственно и все. Запускаем и видим в консоли что-то вроде:
[ bash: ./dbjs.sh
listening on [any] 8880 ...


Далее просто обращаемся к нашему серверу, по указанному порту и получаем вывод:
// http://127.0.0.1:8880 - Выводит список баз данных
{
    fields: [
           "Database"
    ],
    data: [
         [ "information_schema" ],
         [ "test" ]
    ]
}


// http://127.0.0.1:8880/test - Выводит список таблиц базы данных test
{
          fields: [
              "Tables_in_test"
          ],
         data: [
             ["prods"],
             ["shops"],
             ["sp"],
             ["stat"]
         ]
}


// http://127.0.0.1:8880/test.shops - Выводит данные таблицы test.shops

{
     "fields": [
           "id",
           "name",
           "adress"
     ],
     "data": [
           ["1","aaaaa",""],
           ["2","bbbbbbbbb",""],
           ["3","cccccccccccccccc","ccc"]
     ]
}


Скрипт не идеален, но никто не мешает его дорабатывать, если в этом вообще есть нужда.

П.С.: На вопрос: Зачем?, сразу отвечу: по фану. Жизнь должна приносит радость. Мне нравится получать позитив от таких вот нестандартных решений.
Майоров Александр @0xy
карма
133,0
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (20)

  • +9
    Вот он — владелец велосипедных фабрик!
    • +1
      В данном случае, скорей всего производитель =)
    • +4
      Велосипедная фабрика — это новый паттерн проектирования?
  • 0
    Я никогда не понимал зачем люди такие петросянские заголовки делают
    • 0
      Предложите свой вариант.
  • +4
    Вот это правильно, юникс-вей в классическом его понимании. Не факт, что ваше решение будет работать хуже(медленнее, прожорливее), чем «нормальные» способы.
    • 0
      Юникс-вэй — это использовать что-то встроенное, если оно есть, а не переизобретать инструменты.
      • +5
        Sed+bash — это не что-то встроенное? Это самое наипрямое использование юникс-утилит, то, для чего их придумали, для обработки текстов.

        Посмотрю я на вас как вы будете, к примеру, пихать в эмбедед-решение свои непереизобретенные инструменты.
  • +4
    Плохо, однопоточно, надо сделать после принятия соеденения fork для вызова mysql :)
    • 0
      Ну ты же понимаешь, что можно немного усложнить код и избавиться от форка. Ну и кормить запросы в заданное количество mysql клиентов…
  • 0
    mysql -X и xsltproc решили бы вашу задачу быстрее и менее затратно по производительности и памяти. XSLT-программ, которые гонят XML в JSON навалом в сети.
    • 0
      Эта задача решена скорее ради забавы, хотя доля полезности в ней так же присутствует. Если бы задача решалась для продакшена, то этого поста не было бы, а способов 1000 и одна штука имеется с уже готовыми велосипедами.
      • +1
        вот он мой старый велосипед github.com/akalend/ngx_http_handlersocket_json_module
        все собираюсь перепилить в upstream / nonblock вариант… да вот что-то задачи кончились.
        • 0
          Ну, в принципе, полезная штука. Надо будет поизучать на досуге. Спасибо что напомнил о себе ) Давно мы с тобой не общались…
          • 0
            заглядывай highloadblog.ru
          • 0
            тут есть небольшой баг/недоделка — нет перекодировки UTF
  • +5
    Вот дизайнеры и верстальщики играют шрифтами… А программисты играют языком П =) Чего стоят такие вот вещи, как сортировка через слип:

    #!/bin/bash 
    # Sleeping sort 
    
    f(){ 
        perl -e "select(undef,undef,undef,$1*0.01);" 
        echo "$1" 
    } 
    
    while [ -n "$1" ] 
    do 
         f "$1" & 
         shift 
    done 
    wait
    


    $ ./sleepsort 1 4 8 12 10  9 3 2 0
    0
    1
    2
    3
    4
    8
    9
    10
    12
    


    По моему, очень даже весело )
    • 0
      расововерный sleep :)
      Я очень радовался )
  • +1
    Вот китайцы что умеют, если уже есть есть веб-сервер.
  • +5
    image

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.