自我记录的微服务(ArangoDB + swagger)

维护最新的微服务文档仍然需要开发中的最大纪律,并且需要大量的人工成本。 例如,GraphQL提供了一种非常合理的创建文档的方法,其中文档与程序代码有着千丝万缕的联系,这可以保证文档和文档服务的100%符合性。 但是,对于习惯于REST-API的开发人员而言,GraphQL的非常规方法仍然使在实际应用程序开发中推广该技术变得困难。 在这里,您可以回想起SOAP,它早已解决了文档和服务的一致性问题,但是由于过于复杂,它并未在广大开发人员中扎根。

我想找到一种用于开发微服务的技术,这些技术在开发“传统” REST-API微服务时提供相同的程序代码自记录性。 事实证明,他已经存在。

我们定义将参与我们的小例子的演员和表演者。

ArangoDB是一个混合的,面向文档+图形的数据库。

UPD 对该数据库的更详细了解是另一个令人失望的原因。 事实证明,在数据库超出不受可用RAM限制的非限制限制之后,数据库开始变慢-它随服务器一起停止。 同时,有人胆怯地假设向新存储引擎的过渡会更好,但尚未得到证实。

Foxx是内置在ArangoDB数据库中的微服务框架。 它在JavaScript引擎上运行,该JavaScript引擎(与nodejs不同)可以在无限数量的并行线程中同时执行(彼此不阻塞),因此,不需要promise / than / canch和async / await构造。 与不建议滥用服务器过程的mongodb和不谨慎使用存储过程并且肯定不会通过REST-API与客户端(浏览器,移动应用程序等)进行交互的关系数据库相反,它是微服务框架Foxx专为开发与客户端直接通过http协议进行通信的微服务而设计。

Swagger是由大型工具生态系统支持的开源软件环境,可帮助开发人员开发,创建,记录和使用RESTful Web服务。 尽管大多数用户使用Swagger UI识别Swagger,但是Swagger工具包包括对自动文档,代码生成和测试用例生成的支持。

Swagger包含对代码生成的支持这一事实与我们希望得到的情况相反-当代码支持文档生成时。 ArangoDB + Foxx提供给我们的只是相反的选择。 当微服务代码为Swagger生成电路时。 但是,现在您可以验证自己是否已完成了最少的工作。

您必须安装ArangoDB才能执行进一步的操作。

  1. 我们进入管理面板,然后选择用于创建新的微服务的项目Services-> Add service-> New。
  2. 我们在打开的表单中填写所需的表单。 在“文档集合”字段中,添加部署微服务时将创建的文档集合的名称。 例如猫。
  3. 我们单击安装按钮,在将要安装微服务的url字段中输入。

安装微服务时,对于“文档集合”字段中的每个集合(请参阅第2节),将创建使用POST,GET,PUT和DELETE方法实现CRUD操作的路由。 但是,这只是您可以更改,删除,添加新方法的草案。 创建微服务(猫)时,我们选择了一个集合,尽管我们可能没有这样做,但是稍后手动添加了所有内容。

现在,我们的cats集合具有用于CRUD操作的路由,我们可以通过选择API选项卡(服务-> [微服务名称]-> API)开始从数据库管理面板调用这些路由。 此选项卡包含熟悉的Swagger界面。 也可以在外部路由上发布Swagger界面,不仅可以通过管理面板进行访问,还可以将其作为常规URL进行访问。

如果我们尝试使用POST {“ name”:“ Tom”}方法将文档添加到cats集合中,则会显示错误状态。 因为 我们尚未定义的名称字段。 因此,我们将继续使用ArangoDB管理面板。

4.为了更方便地进行开发,ArangoDB提供了开发模式,该模式在“设置”选项卡上启用(服务-> [微服务名称]->设置-设置开发)

现在,您可以更改world服务的代码并立即观察结果(无需额外部署)。 可以在“信息”选项卡上的管理面板中找到微服务程序代码所在的目录(服务-> [微服务名称]->信息)。

让我们看看POST路由的定义是什么样的。

'use strict'; const dd = require('dedent'); const joi = require('joi'); const httpError = require('http-errors'); const status = require('statuses'); const errors = require('@arangodb').errors; const createRouter = require('@arangodb/foxx/router'); const Cat = require('../models/cat'); const cats = module.context.collection('cats'); const keySchema = joi.string().required() .description('The key of the cat'); const ARANGO_NOT_FOUND = errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code; const ARANGO_DUPLICATE = errors.ERROR_ARANGO_UNIQUE_CONSTRAINT_VIOLATED.code; const ARANGO_CONFLICT = errors.ERROR_ARANGO_CONFLICT.code; const HTTP_NOT_FOUND = status('not found'); const HTTP_CONFLICT = status('conflict'); const router = createRouter(); module.exports = router; router.tag('cat'); router.post(function (req, res) { const cat = req.body; let meta; try { meta = cats.save(cat); } catch (e) { if (e.isArangoError && e.errorNum === ARANGO_DUPLICATE) { throw httpError(HTTP_CONFLICT, e.message); } throw e; } Object.assign(cat, meta); res.status(201); res.set('location', req.makeAbsolute( req.reverse('detail', {key: cat._key}) )); res.send(cat); }, 'create') .body(Cat, 'The cat to create.') .response(201, Cat, 'The created cat.') .error(HTTP_CONFLICT, 'The cat already exists.') .summary('Create a new cat') .description(dd` Creates a new cat from the request body and returns the saved document. `); 


验证和文档均基于对象模式的使用。 我们将通过添加名称字段对其进行一些小的更改:

 'use strict'; const _ = require('lodash'); const joi = require('joi'); module.exports = { schema: { // Describe the attributes with joi here _key: joi.string(), name: joi.string().description('cat`s name'), //    }, forClient(obj) { // Implement outgoing transformations here obj = _.omit(obj, ['_id', '_rev', '_oldRev']); return obj; }, fromClient(obj) { // Implement incoming transformations here return obj; } }; 


通过转到API书签,可以确保电路已更改,现在可以将具有名称字段的对象添加到cats集合中。

apapacy@gmail.com
2018年11月12日。

Source: https://habr.com/ru/post/zh-CN429532/


All Articles