Примеры быстрой разработки api на масштабируемом...

29
Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js Тимур Шемсеминов НИИ Системных Технологий, MetaSystems Inc., ITAdapter Inc. mailto:[email protected] https://github.com/tshemsedinov/impress http://habrahabr.ru/users/marcusaurelius/ https://www.npmjs.org/package/impress

Upload: timur-shemsedinov

Post on 26-Dec-2014

500 views

Category:

Software


2 download

DESCRIPTION

Примеры кода приложений и конфигурации сервера с доступом к файлам, памяти, базам данных и параллельной асинхронной обработкой различных типов API запросов с состоянием и без состояния.

TRANSCRIPT

Page 1: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js

Тимур ШемсеминовНИИ Системных Технологий, MetaSystems Inc., ITAdapter Inc.

mailto:[email protected] https://github.com/tshemsedinov/impresshttp://habrahabr.ru/users/marcusaurelius/ https://www.npmjs.org/package/impress

Page 2: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Сервер приложений Impress

• Масштабирование, прозрачное для приложений• Изоляция приложений (память, конфигурация, БД)• Модификация кода без перезапуска• Быстрая отдача статики из памяти (gzip, js min.)• URL-rewriting регулярными выражениями, с внутренним

перенаправлением или внешним HTTP-вызовам• Виртуальные хосты с поддержкой *.domain.com• Кэширование кода, статики и шаблонов в памяти• Возможность запускать на одном tcp порту несколько

приложений и одно приложение на нескольких портах• Server-Sent Events и WebSocket на одном порту• Возможность иметь API без состояния (REST) и с состоянием

(RPC), прилипание по IP и Cookie• Множество других вещей: встроенный механизм сессий,

логирование, IPC и ZeroMQ, драйвера доступа к БД и т.д.

Page 3: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Примеры быстрой разработки API

Общие принципы:• Маршрутизация запросов на основе файловой системы• Каждый обработчик в отдельном файле• Не требуется готовить среду исполнения запроса в обработ-

чиках, т.е. не нужно подгружать библиотеки, устанавливать соединение с БД, строить структуры памяти и т.д., запрос попадает сразу в подготовленную среду, и мы пишем только прикладной код

• У каждого приложения есть свой изолированный глобальный контекст и все, что в него пишется, сохраняет свое состояние между запросами

• Можно ответвлять долгие обработчики (workers) в отдельные процессы

• Осуществляется глобальное (кросс-серверное) межпроцессовое взаимодействие при помощи трансляции событий

Page 4: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

1. Простейший пример обработчика JSON

/example/app/examples/simple/jsonPost.json/post.jsmodule.exports = function(client, callback) { client.context.data = { a: 1 }; callback();}---------------------------------------------------------------HTTP POST /example/app/examples/simple/jsonPost.json{ "a": 1}

Page 5: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

2. Простейший пример обработчика AJAX

/examples/simple/ajaxTest.ajax/get.jsmodule.exports = function(client, callback) { client.context.data = { parameterName: client.query.parameterName, }; callback();}

---------------------------------------------------------------/examples/simple/ajaxTest.ajax/html.templateAJAX Request with parameter returning back in template<br>parameterName: @parameterName@

---------------------------------------------------------------HTTP GET/examples/simple/ajaxTest.ajax?parameterName=parameterValueAJAX Request with parameter returning back in template<br>parameterName: parameterValue

Page 6: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

3. Пример вызова обработчика

/js/init.js$.post('/examples/simple/jsonPost.json', { parameterName: "paramaterValue" }, function(res) { console.log(res.valueLength); });---------------------------------------------------------------HTTP POST /example/app/examples/simple/jsonPost.json{ "status": 1, "parameterValue": "paramaterValue", "valueLength": 14, "requestCounter": 3}---------------------------------------------------------------Console:14

Page 7: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

4. Пример доступа к файловой системе

/examples/simple/fsAccess.json/get.jsmodule.exports = function(client, callback) { var filePath = client.hostDir+client.path+'/test.txt'; fs.readFile(filePath, 'utf8', function(error, data) { client.context.data = { fileContent: data, dataLength: data.length }; callback(); });}---------------------------------------------------------------HTTP GET /examples/simple/fsAccess.json{ "fileContent": "?Example text file", "dataLength": 18}

Page 8: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

5. Пример HTTP-запроса из обработчика

/examples/simple/httpRequest.json/get.jsmodule.exports = function(client, callback) { var req = impress.http.request({ hostname: 'google.com', port: 80, path: '/', method: 'get' }, function(response) { var data = ''; response.on('data', function(chunk) {data=data+chunk;}); response.on('end', function() { client.context.data = data; callback(); }); } ); req.on('error', function(e) { client.context.data = "Can't get page"; callback(); }); req.end();}

Page 9: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

6. Пример доступа к MongoDB (чтение)

/examples/mongodb/getData.json/get.jsmodule.exports = function(client, callback) { dbAlias.testCollection.find({}).toArray( function(err, nodes) { client.context.data = nodes; callback(); } );}

---------------------------------------------------------------HTTP GET mongodb/getData.json[ { "_id": "53547375894c3d3022000001" }]

Page 10: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

7. Примеры доступа к MongoDB

/examples/mongodb/insertData.json/get.jsmodule.exports = function(client, callback) { dbAlias.testCollection.insert(client.query, function(err) { client.context.data = !err; callback(); });}---------------------------------------------------------------/examples/mongodb/getCollections.json/get.jsmodule.exports = function(client, callback) { dbImpress.connection.collections(function(err, collections) { var items = []; for (var i = 0; i < collections.length; i++) { items.push(collections[i].collectionName); } client.context.data = items; callback(); });}

Page 11: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

8. Пример с SQL-запросом (mysql)

/examples/mysql/getCities.json/get.jsmodule.exports = function(client, callback) { dbAlias.query( 'select * from City', function(err, rows, fields) { client.context.data = { rows:rows, fields:fields }; callback(); } );}

Page 12: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

9. Пример с разными типами ресурсов

/examples/complex/getFsMongoRequest.json/get.jsmodule.exports = function(client, callback) { impress.async.parallel({ file: function(callback) { var filePath = client.hostDir+client.path+'/test.txt'; fs.readFile(filePath, 'utf8', function(error, data) { callback(null, data); }); }, request: function(callback) { var req = impress.http.request({ hostname: 'google.com', port: 80, path: '/', method: 'get' }, function(response) { var data = ''; response.on('data', function(chunk) { data = data+chunk; }); response.on('end', function() { callback(null, data); }); } ); req.on('error', function(e) { callback(null, "Can't get page"); }); req.end(); },...

Page 13: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

...продолжение примера

/examples/complex/getFsMongoRequest.json/get.js... mongo: function(callback) { dbAlias.testCollection.find({}).toArray(function(err, nodes) { callback(null, nodes); }); } }, function(err, results) { client.context.data = results; callback(); });}---------------------------------------------------------------------------------{ "mongo": [ { "_id": "53547375894c3d3022000001" } ], "file": "?Example text file", "request": "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n<TITLE>302 Moved</TITLE></HEAD><BODY>\n <H1>302 Moved</H1>\nThe document has moved\n <A HREF=\"http://www.google.com.ua/?gws_rd=cr&amp; ei=OWVWU5nHOqOc4wTbjYDgBw\">here</A>.\r\n</BODY></HTML>\r\n"}

Page 14: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

10. Пример обработчика с состоянием

/examples/memory/stateful.json/get.jsmodule.exports = function(client, callback) { application.stateTest = application.stateTest || { counter: 0, addresses: [] };

application.stateTest.counter++; application.stateTest.addresses.push( client.req.connection.remoteAddress );

client.context.data = application.stateTest; callback();}

Page 15: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

11. Пример обработчика SSE

/examples/events/connect.sse/get.jsmodule.exports = function(client, callback) { client.sse.channel = 'TestEventStream'; callback();}

---------------------------------------------------------------/js/init.jsvar sse = new EventSource("/examples/events/connect.sse");

sse.addEventListener("TestEventStream", function(e) { console.dir({ event: e.event, data: e.data });});

Page 16: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

12. Пример обработчика WebSocket

/examples/events/connect.ws/get.jsmodule.exports = function(client, callback) { var connection = client.res.websocket.accept(); connection.send('Hello world'); connection.on('message', function(message) { connection.send('I am here'); }); connection.on('close', function(reasonCode, description) { console.log('disconnected'); }); callback();}---------------------------------------------------------------/js/init.jsws = new WebSocket("ws://127.0.0.1:80/examples/events/connect.ws");ws.onopen = function() {};ws.onclose = function() {};ws.onmessage = function(evt) { console.log("Message from server: "+evt.data);}

Page 17: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Интроспекция API и файлов

Page 18: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Шаблоны развертывания

• Рекомендации по установке• Конфигурация сервера приложений /config/*.js

• Стратегии запуска (single, multiple, specialization, sticky)• Параметры многопоточности: cluster.js• Порты сетевые интерфейсы и порты: servers.js• Параметры песочников, плагины и зоны видимости• Параметры контроллера прикладного облака: cloud.js• Параметры логирования: log.js

• Конфигурация каждого приложения /applications/name/config/*.js• Подключения к базам данных: databases.js• Виртуалхосты: hosts.js• URL-реврайтинг и обтатный proxy: routes.js• Параметры сессий: sessions.js• Параметры отдачи статики и кеша: files.js• Любые собственные файлы конфигурации приложения

Page 19: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Установка node.js и impress

CentOS 6.5 (64bit) minimalcurl http://.../impress/install.sh | sh---------------------------------------------------------------#!/bin/bashyum -y updateyum -y install wgetyum -y groupinstall "Development Tools"cd /usr/srcwget http://nodejs.org/dist/v0.10.26/node-v0.10.26.tar.gztar zxf node-v0.10.26.tar.gzcd node-v0.10.26./configuremakemake installln -s /usr/local/bin/node /binln -s /usr/local/bin/npm /binmkdir /impresscd /impressnpm install impress

Page 20: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Управление сервисом (демоном)

Если установить в каталог /impress

Исполнится /impress/bin/install.sh• Устанавливается как сервис (демон)• Запускается при старте системы• Перезапускает свои потоки обработки при падениях

/impress/bin/uninstall.sh• Останавливает сервер• Удаляет сервис из системы• Удаляет из автоматического старта

После установи можно пользоватьсяservice impress startservice impress stopservice impress restartservice impress updateservice impress status

Page 21: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Конфигурация сервера приложений

/config/cloud.jsmodule.exports = { name: "PrivateCloud", type: "standalone", controller: "127.0.0.1", pubSubPort: "3000", reqResPort: "3001", health: "2s"}---------------------------------------------------------------/config/cluster.jsmodule.exports = { check: "http://127.0.0.2/", name: "C1", cookie: "node", strategy: "multiple", // single, specialization, sticky workers: os.cpus().length, gcInterval: 0}

Page 22: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Конфигурация сетевых интерфейсов

/config/servers.jsmodule.exports = { www: { protocol: "http", address: "127.0.0.1", port: 80, applications: ["example", "host2"], nagle: true, slowTime: "1s" }, ssl: { protocol: "https", address: "127.0.0.1", port: 443, key: "example.key", cert: "example.cer" }}

Page 23: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Конфигурация плагинов

/config/plugins.jsmodule.exports = [ "db", "db.schema", "db.mongodb", "db.memcached", "db.mysql", "db.mysql.schema", "impress.log", "impress.security", "impress.security.mongodb", "impress.mail", "impress.uglify", "impress.health", "impress.cloud", "impress.geoip", "impress.websocket", "impress.sse"]

Page 24: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Конфигурация логов и песочницы

/config/log.jsmodule.exports = { keepDays: 10, writeInterval: "3s", writeBuffer: 64*1024, fileTypes: [ "access", "error", "debug", "slow" ]}---------------------------------------------------------------/config/sandbox.js module.exports = { modules: [ 'global', 'console', 'process', 'impress', 'db', 'domain', 'crypto', 'geoip', 'os', 'Buffer', 'stream', 'nodemailer', 'net', 'http', 'https', 'dgram', 'dns', 'url', 'path', 'fs', 'util', 'events', 'iconv', 'querystring', 'zlib', 'async']}

Page 25: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Конфигурация хостов и URL-rewriting

/applications/applicationName/config/hosts.jsmodule.exports = [ "127.0.0.1", "mydomain.com", "*.domainname.com",]---------------------------------------------------------------/applications/applicationName/config/routes.jsmodule.exports = [ { url: "/api/(one|two)/(.*)", rewrite: "/example/[1].json?par1=[2]" }, { url: "/api/(name1|name2|name3)/(.*)", rewrite: "/api/[1]/[2]", host: "example.com", port: 80, slowTime: "1s" }]

Page 26: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Конфигурация подключений к БД

/applications/applicationName/config/databases.jsmodule.exports = { mongoTest: { url: "mongodb://hostName:27017/databaseName", slowTime: "2s", collections: ["collection1", "collection2"], security: true, alias: "alias1" }, system: { url: "mysql://user:password@localhost/dbName", slowTime: 1000, alias: "aliasName" }}

Page 27: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Конфигурация сессий и статики

/applications/applicationName/config/sessions.jsmodule.exports = { anonymous: true, cookie: "SID", characters: "ABCDEFGH...fghijkl...456789", length: 64, persist: true, database: "impress"}---------------------------------------------------------------/applications/applicationName/config/files.jsmodule.exports = { minify: false, static: [ "*/css/*", "*/images/*", "*/js/*", "*/favicon.ico", "*/favicon.png" ]}

Page 28: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Примеры и демо-приложение

Page 29: Примеры быстрой разработки API на масштабируемом сервере приложений Impress для Node.js (jsfwdays 2014)

Спасибо за внимание!Прошу задавать вопросы

Тимур ШемсеминовНИИ Системных Технологий, MetaSystems Inc., ITAdapter Inc.

mailto:[email protected]://habrahabr.ru/users/marcusaurelius/https://www.npmjs.org/package/impresshttps://github.com/tshemsedinov/impress