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