编排微服务的标准模式是什么?
如果微服务只知道它自己的域,但是有一个数据流需要多个服务以某种方式进行交互,那么它的方法是什么呢?
假设我们有这样的事情:
为了论证,让我们说一旦订单发货,就应该创建发票.
在某个地方,有人按下GUI中的按钮,"我已经完成了,让我们这样做!" 在一个经典的整体服务架构中,我会说有一个ESB处理这个,或者Shipment服务知道发票服务并且只是调用它.
但是,在这个勇敢的微服务新世界中,人们处理这个问题的方式是什么?
我确实认为这可以被认为是基于意见的.但是它有一个具体的方面,因为微服务不应该做上述事情.因此,必须有一个"根据定义应该做什么而不是",这不是基于意见的.
射击.
假设我们有一个用户,Wallet REST微服务和一个将各种东西粘合在一起的API网关.当Bob在我们的网站上注册时,我们的API网关需要通过用户微服务和钱包通过钱包微服务创建用户.
现在这里有一些可能出错的场景:
用户Bob创建失败:没关系,我们只是向Bob返回错误消息.我们正在使用SQL事务,因此没有人在系统中看到过Bob.一切都很好:)
用户Bob已创建,但在创建我们的Wallet之前,我们的API网关很难崩溃.我们现在有一个没有钱包的用户(数据不一致).
用户Bob已创建,在我们创建电子钱包时,HTTP连接将断开.钱包创建可能已经成功,也可能没有.
有哪些解决方案可以防止这种数据不一致发生?是否存在允许事务跨越多个REST请求的模式?我已经阅读了关于两阶段提交的维基百科页面,它似乎触及了这个问题,但我不确定如何在实践中应用它.这个原子分布式事务:一个RESTful设计文章似乎也很有趣,虽然我还没有读过它.
或者,我知道REST可能不适合这个用例.也许正确的方法来处理这种情况完全放弃REST并使用不同的通信协议,如消息队列系统?或者我应该在我的应用程序代码中强制执行一致性(例如,通过让后台作业检测到不一致并修复它们,或者在我的用户模型上使用"创建","创建"值等具有"状态"属性)?
我试图了解GraphQL最适合在微服务架构中使用的位置.
关于只有1个GraphQL架构作为API网关代理对目标微服务的请求并强制其响应存在争议.微服务仍然会使用REST/Thrift协议进行通信思考.
另一种方法是每个微服务一个多个GraphQL模式.拥有一个较小的API网关服务器,使用请求的所有信息+ GraphQL查询将请求路由到目标微服务.
第一种方法
将1个GraphQL架构作为API网关将有一个缺点,每次更改微服务合同输入/输出时,我们必须在API网关侧相应地更改GraphQL架构.
第二种方法
如果每个微服务使用多个GraphQL模式,那么在某种程度上是有意义的,因为GraphQL强制执行模式定义,并且消费者需要尊重微服务给出的输入/输出.
问题
在哪里可以找到适合设计微服务架构的GraphQL?
您将如何使用可能的GraphQL实现设计API网关?
我很难为微服务架构选择合适/安全的身份验证策略.我在这个主题上发现的唯一SO帖子就是这个:微服务架构中的单点登录
我的想法是在每个服务(例如,身份验证,消息传递,通知,配置文件等)中为每个用户提供一个唯一的引用(在逻辑上user_id与他相当)以及在id登录时获取当前用户的可能性.
从我的研究中,我发现有两种可能的策略:

在此策略中,身份验证应用程序是其中一项服务.但是每个服务必须能够进行转换session_id=> user_id所以它必须简单易行.这就是为什么我想到Redis,它会存储密钥:值session_id:user_id.

在此策略中,会话存储并不重要,因为它仅由身份验证应用程序处理.然后user_id可以转发到其他服务.我想到了Rails + Devise(+ Redis或mem-cached,或cookie存储等),但有很多可能性.唯一重要的是Service X永远不需要对用户进行身份验证.
这两种解决方案如何比较:
或者你可能会建议我在这里没有提到的另一种解决方案?
我更喜欢解决方案#1,但没有找到太多的默认实现,这可以保证我正朝着正确的方向前进.
我希望我的问题不会被关闭.我真的不知道还能在哪里问它.
提前致谢
最近我一直在用docker compose进行一些实验,以便部署多个协作微服务.我可以看到微服务提供的许多好处,现在有一个很好的工具集来管理它们,我认为跳进微服务车并不是很难.
但是,我也一直在尝试Elixir,我非常喜欢它本身提供的好处.鉴于它鼓励将代码打包到多个解耦的应用程序中,并支持热代码升级,您如何将docker与elixir(或erlang)混合使用?
例如,如果我想使用docker因为它提供了dev-prod奇偶校验,那么elixir如何适应它?鉴于docker容器是不可变的,我失去了进行热代码升级的能力,对吗?蓝/绿部署或金丝雀发布怎么样?
我的意思是,我可以用Elixir编写微服务并使用它们就像用任何其他语言编写的那样,多语言无论如何都是微服务的好处之一,但是后来我没有得到使用OTP平台的全部好处,我猜测纯粹的协作erlang应用程序比使用中间队列在以不同(或非)语言编写的微服务之间进行通信更为优化.
对于那些将单片应用程序分解为微服务的人来说,您如何处理拆分数据库的问题.由于性能和简单性原因,我参与的典型应用程序进行了大量的数据库集成.
如果你有两个逻辑上不同的表(如果你愿意的话,有限的上下文),但是你经常对大量的数据进行聚合处理,那么在整体中你更有可能避开面向对象而是使用数据库的标准JOIN功能用于在将聚合视图返回到您的应用层之前处理数据库上的数据.
您如何证明将这些数据拆分为微服务是合理的,因为您可能需要通过API而不是数据库来"加入"数据.
我读过Sam Newman的微服务书,在关于拆分Monolith的章节中,他给出了一个"打破外键关系"的例子,他承认在API中进行连接会变慢 - 但他接着说无论如何你的应用程序足够快,它比以前慢吗?
这看起来有点油腻?人们的经历是什么?您使用了哪些技术来使API连接执行可接受?
为了处理微服务架构,它通常与反向代理(例如nginx或apache httpd)一起使用,并且对于交叉关注问题,使用实现 API网关模式.有时反向代理执行API网关的工作.
很高兴看到这两种方法之间存在明显的差异.看起来API网关使用的潜在好处是调用多个微服务并聚合结果.API网关的所有其他职责可以使用反向代理实现.例如:
基于此,有几个问题:
我做了一些关于微服务的阅读,我有点兴趣.看起来像是有趣的概念.但我想知道,使用微服务而不是单片架构有什么优缺点,反之亦然.
当微服务更合适时,哪里更好地采用单片架构.
我刚读了一篇关于微服务和PaaS架构的文章.在那篇文章中,大约三分之一的时间,作者说(在像Denzy的Denormalize下):
重构数据库模式,并对所有内容进行反规范化,以实现数据的完全分离和分区.也就是说,不要使用提供多个微服务的基础表.不应共享跨多个微服务的基础表,也不应共享数据.相反,如果多个服务需要访问相同的数据,则应通过服务API(例如已发布的REST或消息服务接口)共享它.
虽然这在理论上听起来很棒,但在实践中它还有一些需要克服的严重障碍.其中最大的一点是,数据库经常紧密耦合,每个表与至少一个其他表有一些外键关系.因此它可能是不可能的分区的数据库进Ñ通过控制子数据库Ñ微服务.
所以我要问:给定一个完全由相关表组成的数据库,如何将其归一化为较小的片段(表组),以便片段可以由单独的微服务控制?
例如,给定以下(相当小但是示例性)数据库:
[users] table
=============
user_id
user_first_name
user_last_name
user_email
[products] table
================
product_id
product_name
product_description
product_unit_price
[orders] table
==============
order_id
order_datetime
user_id
[products_x_orders] table (for line items in the order)
=======================================================
products_x_orders_id
product_id
order_id
quantity_ordered
Run Code Online (Sandbox Code Playgroud)
不要花太多时间批评我的设计,我在飞行中做了这个.关键是,对我来说,将这个数据库分成3个微服务是合乎逻辑的:
UserService - 用于系统中的CRUDding用户; 应该最终管理[users]桌子; 和ProductService - 用于系统中的CRUDding产品; 应该最终管理[products]桌子; 和OrderService - 用于系统中的CRUDding订单; 应该最终管理[orders]和[products_x_orders]表但是,所有这些表都具有彼此的外键关系.如果我们将它们归一化并将它们视为整体,它们就会失去所有的语义:
[users] table
=============
user_id
user_first_name …Run Code Online (Sandbox Code Playgroud) 我们想为我们的gRPC微服务构建一个Javascript/HTML gui.由于浏览器端不支持gRPC,我们考虑使用web-socket连接到node.js服务器,该服务器通过grpc调用目标服务.我们很难找到一个优雅的解决方案来做到这一点.特别是,因为我们使用gRPC流来推动我们的微服务之间的事件.似乎我们需要第二个RPC系统,只是为了在前端和node.js服务器之间进行通信.这似乎是很多开销和必须维护的额外代码.
有没有人有这方面的经验,或者知道如何解决这个问题?
microservices ×10
architecture ×4
database ×2
docker ×1
elixir ×1
erlang ×1
graphql ×1
grpc ×1
http ×1
hypermedia ×1
integration ×1
javascript ×1
nginx ×1
node.js ×1
rest ×1
transactions ×1
tyk ×1