Feathers: 微服务:通过拆分服务重构应用程序的推荐方法?

创建于 2016-05-19  ·  27评论  ·  资料来源: feathersjs/feathers

我正在尝试找到一种实用/推荐的方法来提取服务,按照微服务样式将其分为自己的实例。 在这件事上,羽毛的着陆页上有一个有趣的陈述:

面向服务:Feathers从一开始就为您提供了构建面向服务的应用程序的结构。 当您最终需要将应用程序拆分为微服务时,这是一个简单的过渡,并且Feathers可以轻松扩展您的应用程序。

但是,我仍然找不到有关如何用羽毛处理该用例的信息。

实际上,我最初将重点放在两个基本主题上:

  • 通信:我认为应该是一种提取服务并允许原始应用程序继续通信而无需进行大量重写的方法,例如,通过用HTTP请求替换对服务的调用。
  • 身份验证:澄清羽毛在服务分离后如何处理针对服务间通信的身份验证。

提前致谢!

Documentation Question Scaling

最有用的评论

没错,目前没有太多文档,我们不久前创建了https://github.com/feathersjs/feathers/issues/157来进行跟踪。 这是我对您提到的两个主题的一些想法:

假设我们最初有一个具有两个服务的服务器,也许像

app.use('/users', memory())
  .use('/todos', memory());

用户服务所获得的流量超出了一台服务器的处理能力,因此我们想通过为其创建另一个应用程序将其移至另一系统:

// server1
app.use('/users', memory());
// server2
app.use('/todos', memory());

为了使/todos服务现在能够与远程服务通信,我们可以使用Feathers作为客户端来连接到它(Websocket是快速且双向的,为什么不使用它们进行服务器到服务器的通信?):

// server2
const client = require('feathers/client')
const socketClient = require('feathers-socketio/client');
const io = require('socket.io-client');

const socket = io('http://other-server.com');
const otherApp = client().configure(socketClient(socket));

app.use('/todos', memory())
 .use('/users', otherApp.service('users'));

基本上,这将通过websocket连接将用户服务透明地传递给远程服务。 使用原始/users端点的任何内容都无需更改。

至于身份验证,有许多不同的选项。 在上述情况下,最简单的方法是让server1只是将其他服务器的IP地址列入白名单,因为server2仍然是客户端唯一的通信点。 最终, server2可以成为处理用户身份验证的网关,然后将服务调用传递到其他服务器(不必检查身份验证,只需要检查原始IP地址即可)。

所有27条评论

没错,目前没有太多文档,我们不久前创建了https://github.com/feathersjs/feathers/issues/157来进行跟踪。 这是我对您提到的两个主题的一些想法:

假设我们最初有一个具有两个服务的服务器,也许像

app.use('/users', memory())
  .use('/todos', memory());

用户服务所获得的流量超出了一台服务器的处理能力,因此我们想通过为其创建另一个应用程序将其移至另一系统:

// server1
app.use('/users', memory());
// server2
app.use('/todos', memory());

为了使/todos服务现在能够与远程服务通信,我们可以使用Feathers作为客户端来连接到它(Websocket是快速且双向的,为什么不使用它们进行服务器到服务器的通信?):

// server2
const client = require('feathers/client')
const socketClient = require('feathers-socketio/client');
const io = require('socket.io-client');

const socket = io('http://other-server.com');
const otherApp = client().configure(socketClient(socket));

app.use('/todos', memory())
 .use('/users', otherApp.service('users'));

基本上,这将通过websocket连接将用户服务透明地传递给远程服务。 使用原始/users端点的任何内容都无需更改。

至于身份验证,有许多不同的选项。 在上述情况下,最简单的方法是让server1只是将其他服务器的IP地址列入白名单,因为server2仍然是客户端唯一的通信点。 最终, server2可以成为处理用户身份验证的网关,然后将服务调用传递到其他服务器(不必检查身份验证,只需要检查原始IP地址即可)。

感谢您的回复! 您是否打算在官方文档中涵盖此主题(可能是指南的一个小节)? 让我知道我是否可以在这方面做出贡献。

确实。 我们肯定可以使用一些帮助。 也许让我们先收集我们希望在指南中看到的内容,然后制作一些演示应用程序?

d @daffl爆炸了。 我计划在下个月左右正式解决此问题,因为我已承诺就此进行介绍。

@daffl您提到的在后端微服务上使用

是的,但是为什么其他感兴趣的服务也不能使用websocket? 我们正在考虑添加其他提供程序(例如,用于不同的消息传递服务),但是目前,websocket似乎足够快,并且没有写在只能在浏览器中使用的任何地方。

@daffl @ekryski,随着羽毛应用程序的发布,我们还需要解决诸如最少一次交付(acks),幂等,交易,背压(queues)等问题。您是否考虑过类似“ feathers-service-工人?” 外部进程消耗来自持久性amqp(即rabbitmq)队列或redis(使用即kue)的事件?

@daffl我想在您回答之前我不太了解。 只要感兴趣的服务使用Web套接字订阅生产者服务,使用常规事件API在生产者上发布新事件,就足以用羽毛实现它,对吗?

我同意@justingreenberg ,另一个要解决的问题是负责的微服务脱机(崩溃,更新等)时重播请求。 从技术上讲,这也可以通过使用消息队列来解决。

在这方面有什么进展吗? 我非常希望看到一些文档/一个可行的示例。 特别是关于如何处理身份验证。

@imns我们正在努力。 我开始研究示例并拆分应用程序,我们意识到auth的设置方式存在一些限制。 因此,我们目前正在重构auth以更好地支持此功能。 大约要一周才能着陆。

噢,老兄,我现在可以用它了:D

出于好奇,您是否也在重新构造auth以与多个前端一起使用? 我认为当今许多大型应用程序在后端使用微服务,但同时也会分解其前端应用程序。

如果您有一些额外的花销,我认为这本书可以推荐阅读: https ://www.amazon.com/Building-Microservices-Sam-Newman/dp/1491950358/ref=sr_1_1?ie = UTF8&qid = 1469071253&sr = 8-1&keywords =微服务

伙计们,对此有任何更新吗? 谢谢你。

@juanpujol最新信息将始终在票证中。 不过,感谢您的检查。

(这里是marcfawzi)

我没有阅读整个线程,但是我假设我们将能够为每个服务使用一个数据库(在Micreoservices体系结构中,这种分离对于维持抽象至关重要。否则,如果所有服务都共享同一个数据库,那将会阻止人们从定义跨服务模型的关系(违反微服务抽象),而不是使用统一的服务API组成服务?

没有什么能真正防止这种情况发生,我想说的是您不要这样做。 仅当您在ORM级别定义模型和关系时,这才是真正的问题。 我认为通过调用另一个服务在服务级别建立关系不会违反微服务抽象。

是的,正是我的意思。 我倾向于认为,将每个服务具有自己的数据库的服务隔离是通过服务接口而不是在ORM级别强制进行组合的肯定方法。

但是Feathers比Microservices框架更通用,因此在这里一切都很好。 谢谢大卫! 我越深入,它的外观就会越好! 到处都是伟大的工作!

只是以为我会在这里提到这是因为它解决了在微服务环境中使用Feathers带来的一些问题。 这只是第一个实现,但是如果您有任何贡献,请随时访问https://github.com/zapur1/feathers-rabbitmq/issues/1

@ zapur1看起来很有希望...我已发表评论以开始讨论

您还可以将https://github.com/feathersjs/feathers-sync与RabbitMQ,Redis或MongoDB一起用作服务之间的消息代理,以使它们保持同步。

@ekryski feathers-sync解决了一个不同的问题,如果您只希望在命名服务(不是Feathers服务,而是微服务样式服务)的范围内接收一次事件,该怎么办? 如果您有一个服务的多个实例,这些实例从一个API应用程序接收事件,那么每个人都会收到一个事件,该事件很可能会与在完全相同代码的多个实例上接收到该事件时所采取的操作重复。

@ekryski我再次查看了回购协议,zapur1 / feathers-rabbitmq解决了您在“注意事项”中提到的确切问题

如果我通过socketClient将服务1连接到服务2,那么如果我的服务2具有多实例,如何实现负载平衡:(

如果我创建了一个单独的通过socketClient连接的服务器端应用程序,那么验证身份的最佳方法是什么,以便无论设置了什么限制,任何服务都可用。

我在https://github.com/kalisio/feathers-distributed上加了2美分,它的目的是部署N根羽毛应用程序,这些应用程序将不同的服务一起交谈,以便您可以独立开发每个应用程序。 据我所知,它与https://github.com/feathersjs/feathers-sync有所不同,

  • 认证管理
  • API网关和负载平衡
  • 远程钩子调用
  • ...

@daffl在您给出的涉及服务器1和服务器2的示例中,如何保护服务器2中的/users服务? 如果我们在服务器2中定义了该服务,则可以在特定服务钩子文件中使用钩子,但是由于我们正在执行app.use('/users', otherApp.service('users')); ,我们如何确保仅从服务器2对该服务的调用用户是否先通过身份验证?

编辑:
Nvm,我想我有个主意:我们可以执行类似const usersService = app.service('users')然后执行usersService.hooks(hooks) ,其中的钩子具有确保端点安全所需的auth钩子?

我在https://stackoverflow.com/questions/41076627/evaluating-featherjs-authentication-needs/41095638#41095638中写了更多有关如何进行分布式身份验证的内容:

拆分服务的方式有几种,每种方式各有优缺点。 对于Feathers来说,普遍重要的一件事是没有会话,只有JSON Web令牌。 JWT是无状态的,并且可以由共享相同机密的任何服务器读取,因此不必有中央会话存储。 我可以想到的两个主要选项是:

  1. 有一个处理授权和管理所有连接的客户端的主应用程序,但是它们没有与数据库进行对话的服务,而是连接到内部网络中单独的单个API服务器。 这是较容易的设置,其优点是内部API服务器可以非常简单,并且根本不需要身份验证(因为允许主应用程序执行所有操作,并且将根据经过身份验证的用户限制进行查询)。 缺点是主应用程序仍然是瓶颈(但由于其基本上充当了内部API的代理,因此负载减少了)。

my50m

  1. 每个客户端都使用JWT连接到所需的每个API服务器。 JWT由单独的身份验证(或用户)API创建。 这是更具可扩展性的解决方案,因为唯一的瓶颈是从公共用户服务中检索最新的用户信息(这可能并不总是必要的)。 缺点是,在客户端进行管理更加复杂,并且必须在每台服务器上配置身份验证(至少对于JWT)。 但是,由于JWT的无状态性,因此不需要任何共享会话。

lw1bg

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

Vincz picture Vincz  ·  4评论

arve0 picture arve0  ·  4评论

NetOperatorWibby picture NetOperatorWibby  ·  4评论

RickEyre picture RickEyre  ·  4评论

eric-burel picture eric-burel  ·  3评论