RESTful MySql
0. What the fuck your RESTful hm.. ?
Представим себе любое веб приложение. Как взаимодействовать с ним все мы знаем и умеем? Конечно же с помощью основных HTTP методов GET/POST.
Наверняка многие уже знают или слышали про методы такие как PUT/DELETE/PATCH и так далее.
Принцип не отличается от известных всеми GET/POST, где
GET - получить "контент"
POST - отправить "контент"
DELETE - удал.....
PUT - обнов....
Если подсознательно дополнил определения, поздравляю, ты уже разобрались в принципе RESTful. Это тот же HTTP, где позиция метода запроса определяет поведение приложения.
Иначе говоря RESTful представление позволяет нам к примеру обновлять записи путем простого указания PUT в запросе, удалять посредством DELETE.
1. Introduce
Общие черты основного принципа RESTful вспомнили. На примере точно вспомните, наверняка взаимодействовали уже ранее с данным представлением.
Все то что многие так долго искали, а кто-то просто хотел, но не мог сформулировать.
Пришло время научится делать из любой mysql базы полноценную RESTFful прослойку и да она будет работать по HTTP протоколу. Даже не придётся в очередной раз гуглить, лезть на форума при составлении SQL запроса, а вспомните сколько ужаса связанного с экранированием спец символов и тому подобное.
2. Getting Started
Решение является кроссплатформенным, заведётся как на OS Windows, так и на unix-подобных системах с установленной node (requires node >= 7.6.0).
1) Убедимся что у нас стоит пакет node (https://nodejs.org/en/download/), и работает npm менеджер пакетов (ставиться вместе с node).
После установки Открываем новое окно терминала
C:\> node -v v12.18.4 C:\> npm -v 6.14.8
2) Установим пакет xmysql который будет делать магию. (офф репозиторий)
Запустим терминал/консоль (с правами Администратора)
C:\> npm install -g xmysql
Если не увидели ошибок, можем приступать.
У кого разбор полетов, следуйте на страничку репозитория проекта, изучите решения или задайте вопрос разработчику (https://github.com/o1lab/xmysql)
3) Ну и конечно же нам нужна рабочая mysql бд.
Я буду использовать локальную версию MariaDB 10.3.26. Вы можете любую какая вам по душе.
C:\> xmysql
4) Пропишем в параметрах наши значения для подключения к базе данных и укажем имя базы данных с которой будем работать
C:\> xmysql -h localhost -u root p "" -d open_disposable_base
Убедитесь что у вас не занят порт 3000, и добавьте в исключение при первом запуске сработает брандмауэр windows.
5) Проверим локальный адрес по порту 3000, на нем должен подняться RESTful HTTP нашей базы (по умолчанию http://localhost:3000)
Попробуем отправить запрос по этому адресу
p.s. можно также просто отрыть в браузере http://localhost:3000
На корневой странички увидим все доступные пути routing и методы взаимодействия RESTful (какой метод использовать в HTTP запросах)
На данном этапе мы настроили и запустили все необходимое.
!!!!Однако будьте внимательны!!!!!
Если запустите на выделенном сервере и не позаботитесь о доступе по порту 3000, скорее всего любой желающий сможет получить данные с базы, или куда похуже через методы upload/download.
Решения легко найти в google. Вариантов довольно много. От парольного доступа до исключения на сетевом уровне.
3. Query processing
Разберем пару примеров, попробуем на что способен этот зверь =)
Модель построения запросов
host:port/api/[table_name]/?[method]
Модель построения запросов с перечислением параметров
host:port/api/[table_name]/?[method]=([param1],[param2]..)
Полный список https://github.com/o1lab/xmysql#api-overview
- Просмотр содержимого таблицы (аналогия запроса ниже)
sql select * from `open_disposable_base` limit 0,20
GET /api/disposable_emails/
[ { "id": 1482, "domain": "ce.mintemail.com", "created_at": "2018-05-31T01:25:56.000Z", "updated_at": "2018-05-31T01:25:56.000Z", "deleted_at": null } ]
- Получить кол-во в таблице.
GET /api/disposable_emails/count
[ { "no_of_rows": 663 } ]
Пример передачи параметров:
/findOne?_where=([Column],[Operator],[SearchValue])
[SearchValue] = ce.mintemail.com -искомое значение
[Column] = domain - имя столбца
[Operator] = eq - эквивалентно (полный список)
- Поиск записи по указанному столбцу
GET /api/disposable_emails/findOne?_where=(domain,eq,ce.mintemail.com)
[ { "id": 1482, "domain": "ce.mintemail.com", "created_at": "2018-05-31T01:25:56.000Z", "updated_at": "2018-05-31T01:25:56.000Z", "deleted_at": null } ]
- Фильтрация по столбцам, перечисляем через запятую имена столбцов. Также инверсионный вариант с добавлением “-” перед именем.
GET /api/disposableemails/?fields=id,domain
[ { "id": 1481, "domain": "cbair.com" }, { "id": 1482, "domain": "ce.mintemail.com" }
GET /api/disposableemails/?fields=-domain
[ { "id": 1481, "created_at": "2018-05-31T01:25:56.000Z", "updated_at": "2018-05-31T01:25:56.000Z", "deleted_at": null }, { "id": 1482, "created_at": "2018-05-31T01:25:56.000Z", "updated_at": "2018-05-31T01:25:56.000Z", "deleted_at": null }
- Создаем пагинацию (полезно при очень больших таблицах)
GET /api/disposableemails/?fields=domain&_pp=1&ze=3
[ { "domain": "cheaphorde.com" }, { "domain": "chef.asana.biz" }, { "domain": "chielo.com" } ]
- Также стоит отметить возможность работы с файлами. Upload, Download, в параметрах xmysql есть флаг указания каталога для файлов.
- В документации описан также метод Dynamic queries, эта возможность присутствует в случае локального mysql сервера.
POST /dynamic
{ "query": "select * from ?? limit 1,20", "params": ["customers"] }
4. Work in ZP, try multitread inserts
На коленке написал минимальный код, для быстрого теста и попробовать многопоточную вставку. Общий принцип как начать внедрять в свои проекты xmysql.
string xsqlHost = "http://localhost"; // xmysql hostname or IP string xsqlPort = "3000"; string xsqlTable = "test_multithread"; // Table name string xsqlBase = string.Concat(xsqlHost, ":", xsqlPort); // base path for query string xsqlGetTable = string.Concat(xsqlBase, "/api/", xsqlTable); // path to query for table var xsqlHelth = new HttpRequest().Get(xsqlBase+"/_health").ToString(); // check avalible and status mysql project.SendInfoToLog(xsqlHelth); var xsqlRoutes = new HttpRequest().Get(xsqlBase).ToString(); // parse all avalible routes project.Json.FromString(xsqlRoutes); // show routes with methods in zp varibles (json)
Плавненько подходим к концовке. Читать данные хорошо, но что же с записью/изменению/обновлению?
Произвели пару тестов, в окружении локально поднятой базой, для общей оценки и применения xmysql при работе в многопоточном режиме.
Схема заполняемой таблицы выглядело примерно след. образом:
CREATE TABLE `test_multithread` ( `id` int(11) NOT NULL AUTO_INCREMENT, `domain` varchar(255) NOT NULL, `add_date` timestamp DEFAULT CURRENT_TIMESTAMP PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5958 DEFAULT CHARSET=utf8;
Из списка загружались домены, причем умышленно по одному, и аналогично происходила вставка по одному INSERT.
Так делать не желательно, в xmysql помимо add row есть и пакетные обработки CREATE, LIST, DELETE. Прошу заметить, средствами слоя xmysql параметры переданные в теле POST запроса преобразуются в стандартный пакетный INSERT.
Первый тест обычными циклами средствами zp, 2 кубика, один из них шлет POST с параметром "domain=test.com"
Второй тест с использованием Threading.Tasks.Parallel.For
Для понимания кусок кода который отрабатывал указанное кол-во циклов параллельно
var listparams = project.Lists["domains_becnh"]; System.Threading.Tasks.Parallel.For(0, icount, (i, parallelLoopState) => { string domain = listparams[0]; listparams.RemoveAt(0); using (var request = new HttpRequest()) { var reqParams = new RequestParams(); reqParams["domain"] = domain; string addRow = request.Post(xsqlGetTable, reqParams).ToString(); } return; });
В конечном итоге протестировать удалось далеко еще не все.
Однако как видите, даже по одиночной вставке работает более чем.
Скорость вставки в моем случае следующие:
- 500 строк 25 потоками = 500 rows added in 7110,4820ms
Используя параллельные потоки (parallels threads):
- 100 rows added in 205,8456ms ( 2,1 second )
- 500 rows added in 4619,1725ms ( 4,6 second )
- 1000 rows added in 7503,2164ms ( 7,5 second )
p.s. судя по минимальному просмотру исходного кода xmysql, я не углядел работу с транзакциями и т.д. Данный вопрос оставил на потом. Убедитесь в отсутствие необходимости локов на уровне бд если вам будет необходимо много удалять строк и тд. Надеюсь там все хорошо в этом плане, в любом случае попробуйте перед тем как бежать переносить все на xmysql.
Проект неплохо вдохновил на интересные идеи и решения. Так-же есть куча альтернативных решений, в целом личное мнение xmysql вполне способен на роль вспомогательную в проектах. Но в в идеале нужно обертку. Вполне возможно в скором времени она появится...
Следите за новостями, прокачивайте умы - C# for ZennoPoster