建议和反馈

请填写你的反馈内容

通过高级NODE.JS开发具有单片核心的微服务

2019-10-03 ·1425次阅读 ·读完需要24分钟

配方概述

使用Seneca实施微服务

Seneca是一个Node.js框架,用于使用具有整体核心的微服务架构来创建服务器端应用程序。

之前,我们在微服务架构中进行了讨论,我们为每个组件创建一个单独的服务,因此您一定想知道使用框架创建服务的意义何在,只需编写一些代码来侦听端口并回复请求就可以完成服务。嗯,编写代码以发出请求,发送响应和解析数据需要大量时间和工作,但是像Seneca这样的框架使这一切变得容易。同样,将单核的组件转换为服务也是一项繁琐的任务,因为它需要大量代码重构,但是Seneca通过引入动作和插件的概念使其变得容易。最后,以任何其他编程语言或框架编写的服务将能够与Seneca服务进行通信。

在Seneca中,动作代表特定的操作。一个动作是一个功能

由对象文字或称为操作模式的JSON字符串标识。


在Seneca中,使用操作编写了单核核心组件的这些操作,我们稍后可能希望将其从单核转移到服务,并通过网络将其公开给其他服务和单核。


Seneca服务将操作公开给其他服务和整体内核。在向服务发出请求时,我们需要提供与服务中要调用的动作的模式匹配的模式。


Seneca也有插件的概念。seneca插件实际上是一组操作,可以轻松分发并插入到服务或整体内核中。

随着我们的整体核心变得越来越大和复杂,我们可以将组件转换为服务。即,将某些组件的动作移至服务。


创建您的第一个Seneca应用程序

让我们使用Seneca创建一个基本应用程序以演示如何使用它。我们将创建一个允许用户登录并注册的应用程序。这将是一个演示应用程序,目的只是演示如何创建操作,插件和服务,而不是登录和注册功能的工作方式。

在继续之前,请创建一个名为seneca-example的目录,并在其中放置一个名为package.json的文件。在seneca-example目录中,我们将放置我们的服务和整体内核。在package.json文件中,放置以下代码,以便npm能够下载我们应用程序的依赖项:

“ name”:“ seneca-example”,“ dependencies”:{ 

“ seneca”:“ 0.6.5” , “表达” : ”



在这里,我们使用的是Seneca版本0.6.5。确保您也使用相同版本,以避免代码不兼容。

现在,在seneca-example目录中运行npm install命令以在本地安装Seneca和其他软件包。

现在创建一个名为main.js的文件,它将成为我们服务器端应用程序的整体核心。

整体式内核和服务都是通过编程实现的seneca实例。将此代码放在main.js文件中,以创建一个seneca实例:

var seneca = require(“ seneca”)(); 

现在使用此seneca对象,我们将添加操作,调用操作,添加插件以及所有内容。


创建动作

让我们为登录和注册功能创建动作,并将其放置在main.js文件中。要创建动作,我们需要使用seneca对象的add方法。add方法的第一个参数采用JSON字符串或对象作为操作标识符(称为模式以标识操作)。第二个参数是将在调用操作时执行的回调。

将此代码放在main.js文件中,该文件将创建用于登录和注册的两个操作,

如下所示:

seneca.add({role:“ accountManagement”,cmd:“ login”},function(args,response){ 

});


seneca.add({role:“ accountManagement”,cmd:“ register”},function(args,response){ 

}); 

我们将在本文后面的部分中看到动作主体的代码。

角色和cmd属性没有什么特别的。您也可以使用任何属性名称。

第二个参数是回调,将在调用操作时调用。

如果存在多个具有相同模式的动作,则后者会覆盖其他动作。

我们需要使用seneca对象的act方法来调用实例本地操作或驻留在其他服务上的操作。act方法的第一个参数是与操作匹配的模式,第二个参数是在调用操作后将执行的回调。

这是一个示例代码,显示了如何调用上述两个操作:

seneca.act({role:“ accountManagement”,cmd:“ register”,用户名:“ narayan”,密码:“ mypassword”}},function(error,response ){ 

});


seneca.act({角色:“ accountManagement”,cmd:“ login”,用户名:“ narayan”,密码:“ mypassword”},函数(错误,响应){ 

});

一旦操作的结果到达,传递给act方法的回调将异步执行。


在这里,我们传递给act方法的对象比它应该匹配的动作模式具有两个额外的属性。但是,该动作仍会被匹配和调用,因为如果传递给act方法的模式具有比其应匹配的动作模式更多的属性,则Seneca会找到所有属性均位于传递给act方法的模式中的动作模式,并调用具有最多匹配属性的对象。

如果Seneca找到具有相同数量的匹配属性的多个动作模式,

则它们将按字母升序进行匹配。



创建插件

Seneca插件只是打包在一起的一组相关动作。通过编程,可以使用函数或模块来创建seneca插件。

插件使在应用程序之间分配一组操作变得容易。您还将在npm维护的在线公共软件包注册表中找到seneca插件。例如,有一个seneca插件,提供了与MongoDB数据库一起使用的操作。仅需一行代码,即可将该插件插入单片内核或服务。

默认情况下,当我们创建seneca实例时,Seneca会安装四个内置插件。这些插件是basic,transport,web和mem-store。

首先让我们使用一个函数创建一个插件。函数名称是插件名称,插件也可以具有初始化动作,将插件附加到seneca实例后将立即调用该动作。

因此,让我们创建一个名为account的插件,并在其中放置登录和注册操作,稍后,我们将创建服务并在其中移动操作。删除我们之前在main.js文件中定义的操作,并放置以下代码:

function account(options)

this.add({init:“ account”},function(pluginInfo,response){console.log(options。消息); 

response(); 

})


this.add({role:“ accountManagement”,cmd:“ login”},function(args,response){ 

});


this.add({role:“ accountManagement”,cmd:“ register”},function(args,response){ 

}); 

}


seneca.use(帐户,{消息:“已添加插件”}); 

在这里,我们定义了一个名为account的函数,并使用seneca对象的use方法将其附加。要附加多个插件,我们可以多次调用use方法。

init:account操作是添加插件后Seneca调用的初始化操作。这可以用来做诸如建立数据库连接之类的事情,或者做插件动作所依赖的其他事情。

插件内的this关键字指的是seneca实例。

让我们使用模块创建相同的插件,以便轻松分发该插件并将其放置在npm注册表中。创建一个名为account.js的文件,并将其放置在seneca-example目录中。account.js是插件模块。将此代码放在account.js文件中:

module.exports = function(options)

this.add({init:“ account”},function(pluginInfo,response){console.log(options.message); response 

() ; 

})


this.add({role:“ accountManagement”,cmd:“ login”},function(args,response){ 

});


this.add({role:“ accountManagement”,cmd:“ register”},function(args,response){ 

});


返回“帐户”;

}


这是匿名函数返回的字符串中的插件名称。

删除我们先前在main.js文件中定义的插件代码,并放置

以下代码:

seneca.use(“ ./ account.js”,{消息:“已添加插件”}); 

在这里,要附加插件,我们提供了模块路径。


 


创建服务

服务是一个seneca实例,它通过网络公开一些操作。让我们创建一个公开登录和注册操作的服务。

在seneca-example目录中创建一个account-service.js文件,它将充当服务。然后在其中放置以下代码以创建公开登录和注册操作的服务:

var seneca = require(“ seneca”)(); seneca.use(“ ./ account.js”,{消息:“已添加插件”}); 

seneca.listen({port:“ 9090”,pin:{role:“ accountManagement”}}));

在这里,我们首先创建了一个seneca实例。然后,我们通过插件添加了动作。您也可以使用seneca对象的add方法手动添加操作。最后,我们通过HTTP协议公开了这些操作。Seneca还支持其他协议,但是我们将坚持使用HTTP,因为它是最常用的协议。

seneca.listen创建一个HTTP服务器来侦听请求。我们还提供了端口号和引脚,它们是可选的。默认端口为10101,默认情况下,如果未提供,则没有引脚。

您一定想知道什么是图钉,它的用途是什么?好吧,您可能并不总是希望通过网络公开服务的所有操作。在这种情况下,您可以为pin属性提供一个模式,服务器将处理与该pin模式匹配的这些请求。

现在,要使其他服务或单核能够调用该服务的操作,它们需要注册该服务。


从main.js文件中删除以前的插件附件代码,并添加

以下代码来注册服务:

seneca.client({port:“ 9090”,pin:{role:“ accountManagement”}})); 

在这里,我们通过提供端口号和引脚来注册服务。它们都是可选的。如果我们不使用任何端口号,则默认为10101。如果服务位于其他服务器上,则应使用host属性提供IP地址。

客户端方法附带的引脚用于告知seneca实例服务公开了哪些操作。这是完全可选的。Seneca不会将请求发送到与密码模式不匹配的服务。

您可以通过多次调用client方法来添加任意数量的服务。

当您调用act方法来调用操作时,seneca实例首先在本地查找操作,然后再请求服务。如果在本地找不到,它将检查具有图钉的服务以查看其是否匹配。如果引脚匹配,则它将请求发送到该特定服务。最后,如果任何一个引脚都不匹配,它将

一个一个地向所有其他没有引脚的服务发送请求,直到从其中一个获得有效响应为止。

您还可以通过将GET请求发送到以下类型的URL来手动调用服务的操作:

http:// localhost:9090 / act?role = accountManagement&cmd = login&usernam e = narayan&password = mypassword

您也可以使用POST请求来调用服务。使用CURL的方法如下:

curl -d'{“ role”:“ accountManagement”,“ cmd”:“ login”,“ username”:“ narayan”,“ passw ord”:“ mypassword”}'-v http:// localhost:9090 / act


储存资料

Seneca提供了一种内置的机制来存储数据。塞内卡(Seneca)提供了一些内置动作,使我们可以存储数据。内置操作默认使用mem-store存储数据。mem-store是一个异步的内存存储系统。

您可以使用默认存储机制创建应用程序。如果要更改基础存储系统,只需为该特定存储系统安装插件,该插件将覆盖内置存储操作,因此您不必重构任何代码。


进行CRUD操作的内置操作如下:


角色:实体,cmd:负载,名称:<实体名称>:这用于使用其ID检索实体。可以将一个实体视为MySQL中的一行。每个实体都有唯一的ID。

角色:实体,cmd:保存,名称:<实体名称>:这用于更新(如果提供实体ID)或添加不存在的实体。实体以对象的形式存储和检索。

角色:实体,cmd:列表,名称:<实体名称>:这用于列出与查询匹配的所有实体。

角色:实体,cmd:删除,名称:<实体名称>:这用于使用其ID删除实体。

Seneca还提供了一些包装函数,可提取这些动作并使调用这些动作变得容易。这些函数是load $,save $,list $和remove $。

让我们实现登录和注册操作,以允许我们登录以及注册新帐户。

这是帐户操作的实现。更新帐户中的此代码。js文件:

this.add({role:“ accountManagement”,cmd:“ login”}},function(args,

response ){ var account = this.make(“ accounts”);


account.list $({{username:args.username,password:args.password},function(error,Entity){ 

if(error)return response (error);


if(entity.length == 0)

{ response 

(null,{value:false}); 

else 

response(null,{value:true}); 

}); 

}); 

传递给add方法的回调的第一个参数包含对与操作模式匹配的对象的引用。

在这里,我们首先调用seneca对象的make方法。它用于获取实体商店的引用。例如,对于MySQL,make方法获取对表的引用。

然后,我们将查找是否有通过act方法传递用户名和密码的实体。当实体作为对象添加时,要查询实体,我们需要传递一个对象。现在,list $查找具有相同用户名和密码的所有实体。

我们正在将回调传递给$ list方法,该方法将在检索数据后异步调用。此回调有两个参数,即,第一个参数是存在错误的错误对象,否则为null。同样,

第二个参数是找到的与给定对象匹配的实体数组。

为了使操作能够响应,它需要通过将对象作为第二个参数传递给操作回调的第二个参数。如果发生错误,我们需要在第一个参数中传递错误。

同样,现在让我们为注册操作编写代码,如下所示:

this.add({role:“ accountManagement”,cmd:“ register”},function(args,

response ){ var account = this.make(“ accounts” );


account.list $({{username:args.username},function(error,Entity){if(error)return response(error);


if(entity.length == 0)

var data = accounts.data $({用户名:args.username,密码:args.password})


data.save $(function(error,entity){if(error)return response(error);


response(null,{value:true}); 

}); 

else 

response(null,{value:false}); 

}); 

});


在这里,大多数代码都是可以理解的,因为它的工作方式与之前的操作相同。为了存储数据,我们通过传递要存储的实体,使用data $方法创建了一个新的实体存储引用。然后,我们调用save $方法保存实体。


整合Express和Seneca

我们已经完成创建登录和注册操作。现在,由于我们的后端将由一个应用程序使用或可能表示为一个网站,因此我们需要向将使用它们与服务器进行通信的客户端提供URL。

整体内核是我们服务器端应用程序的一部分,客户端可以与大多数功能进行交互。如果需要,客户端还可以直接与服务交互以获取某些特定功能。

因此,我们需要在服务器端应用程序的整体核心和服务中使用某种网站开发框架。我们将使用Express,因为它是最受欢迎的一种。

Seneca还提供了一种将URL映射到操作的内置方法,也就是说,对HTTP服务器发出的请求可以自动映射到特定的操作以调用它们。这是使用定义对象完成的,该对象的属性定义了从URL到操作模式的路由映射。此内置方法定义的路由映射与所使用的框架无关。定义定义对象之后,我们需要特定于Web服务器框架的插件,该插件将使用定义对象捕获URL并将其解析为操作模式。定义对象允许您附加回调,该回调将通过参数获取操作的响应,然后回调可以将数据以所需的任何格式返回给用户。

请使用内置方法,因为它定义的路由映射与所使用的框架无关。


将以下代码添加到main.js文件中,以在其中启动Express服务器:

var app = require(“ express”)(); app.use(seneca.export(“ web”))app.listen(3000); 

在第二行,我们导出由seneca-web插件提供的中间件功能。seneca-web是直接集成Seneca和Express的插件,即使用Express框架的定义对象将URL转换为动作模式。仅当我们使用定义对象定义路由映射时才需要。我们不会使用定义对象,但是我们仍然应该使用seneca-web,因为如果使用这些插件,某些第三方插件可能会使用定义对象。例如,如果您使用的是seneca-auth插件,则必须包括第二行。

我们希望用户能够使用/ account / login路径登录并使用/ account / register路径进行注册。用户将通过查询字符串提供用户名和密码。这是定义用于处理HTTP登录和注册请求的路由的代码:

app.get('/ account / register',function(httpRequest,httpResponse,next)

httpRequest.seneca.act({role:“ accountManagement”,cmd :“注册”,用户名:httpRequest.query.username,密码:httpRequest.query.password},函数(错误,响应){ 

if(错误)return httpResponse.send(错误);


if(response.value == true)

httpResponse.send(“帐户已创建”); 

else 

httpResponse.send(“似乎已经存在具有相同用户名的帐户”); 

}); 

});


app.get('/ account / login',function(httpRequest,httpResponse,next){httpRequest.seneca.act({role:“ accountManagement”,cmd:“ login”,

用户名:httpRequest.query.username,密码:httpRequest .query。password 

},函数(错误,响应){如果(错误)返回httpResponse.send(错误);


if(response.value == true)

httpResponse.send(“已登录!!!”); 

else 

httpResponse.send(“请检查用户名和密码”); 

}); 

}); 

在这里,我们根据URL请求的路径调用适当的操作。

在这里,我们没有使用seneca.act,而是使用httpRequest.seneca.act,因为我们之前导出的中间件函数添加了一个新的seneca属性,以请求每个HTTP请求的对象。此属性继承实际的seneca实例。第三方插件中的操作会将属性形式的信息添加到seneca属性中,以便与其他路由处理程序共享与特定HTTP请求有关的信息。即使使用seneca.act,上述代码也将以相同的方式运行,但是使用httpRequest.seneca.act是一个好习惯,因为我们可能会使用此类插件。您自己的路由处理程序也可以使用httpRequest。seneca.act彼此传递与seneca相关的信息。

现在,要运行该应用程序,请先运行account-service.js文件,然后运行

main.js文件。然后,您可以使用以下URL登录并注册:


http:// localhost:8080 / account / login?username = narayan&password = m ypassword

http:// localhost:8080 / account / register?username = x&password = myp密码

在这里,我们看到了如何创建Web界面,供应用程序使用或在网站的情况下提供HTML页面。

如果我们希望其他服务来处理某些请求,我们还可以将Express的路由移动到服务。


评论(0)问答(0)
请先登录或注册

请先登陆或注册

相关推荐

王佳柏:主流币BTC及ETH 11.12晚间行情分析

比特币晚间八点左右算是今日振幅最宽的一个时间段,先是冲高至8880后直线回落探底8668,这200多点的幅度波动,在这横盘震荡行情中显得格外特别,不过上下两端的分界线仍旧没有有效的突破,所以行情并未出......
王佳柏 · 2019-11-12
57阅读 · 0赞赏 · 0问答

王佳柏:比特币上行受阻下行受限 行情处于低位震荡

比特币从低位8611收回后,行情就一直伺机向上冲刺,可是上冲并不能持久,也许是上方的压力太大或是量能还未续足更或是并未从跌势中完全走出需要时间,总而言之上行中断后回撤,行情处于8750一线震荡运行。小......
王佳柏 · 2019-11-12
90阅读 · 0赞赏 · 0问答

React教程:以太坊分布式应用

ICO,加密,区块链,DAPP。如今,每个人都在讨论它(或至少听取了教训)。今天,我将向您展示如何使用ReactJS在以太坊区块链上创建您的第一个分布式应用程序。我们要建造什么我们将创建自己的令牌,该......
仍然 · 2019-11-12
161阅读 · 0赞赏 · 0问答

以太坊和智能合约简介:可编程区块链

您是否曾经问过自己一个问题:“如果该服务或应用程序的提供者消失了,将会发生什么?” 如果您有,那么了解以太坊可以为您带来很大的改变。以太坊是一个运行去中心化应用程序的平台:不依赖任何中央服务......
Rooney · 2019-11-12
152阅读 · 0赞赏 · 0问答

区块链–使用Visual Studio的以太坊Hello World

本文介绍了有关如何使用Visual Studio入门以太坊 Hello World程序的提示。如果我错过提及一个或多个要点,请随时发表评论/建议。另外,对错字也很抱歉。以下是关键步骤:Visual S......
节点 · 2019-11-12
240阅读 · 0赞赏 · 0问答

王佳柏:比特币空方势力仍显强势 跌势即将上演

比特币的暴跌在昨日下午才刚刚被遏制住,虽说向上拉升并未出现,但是小幅反弹的力量却频频发生,整体行情走势以震荡运行为主;可是这整夜的震荡休整并未等到多方的强势反攻及上涨量能蓄力充足,而是很大可能的面临着......
王佳柏 · 2019-11-12
186阅读 · 0赞赏 · 0问答

海贼 king

1090

LK币

1

粉丝

25

笔记

感谢"海贼 king"

这篇精彩的笔记,目前已经帮助

  • 0
  • 1
  • 4
  • 2
  • 5
喜欢0
链客社群 加入

微博进入

商务合作>

广告投放>

公司名称:北京链客行科技有限公司

联系方式:010-67707199

ICP备案号:京ICP备18032136号

Copyright:链客区块链技术问答社区 版权所有

感谢您的提问,问题被社区永久收入以便新人查看。一定要记得采纳最佳答案哦!加油!

感谢您的善举,每一次解答会成为新人的灯塔,回答被采纳后获得20算力和相应的LK币奖励

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!