目前我有一个设置,我的客户(网络应用程序,iOS应用程序等)通过REST调用与我的后端API .NET Web应用程序(Nancy)对话。没什么特别的。
我现在需要将此API拆分为微服务,其中每个服务都可以单独升级/部署。
我的主要API(公共)只会执行身份验证,然后调用我的一个微服务,它将位于我的私人网络中。
我可以在主API与其他微服务API之间进行通信的不同方式是什么?每种方法的优缺点是什么?
通信需要是实时的 - 例如请求来自浏览器/设备,主API执行身份验证,然后调用微服务API然后返回响应。所以我不能使用像队列或pub / sub这样的东西。它不一定需要使用HTTP,但它需要是实时通信(请求/响应)。我还有其他需要与这些微服务交谈的服务(WebJobs,云服务等)(它们也在私有网络中)。
想到的唯一方法是简单的基于REST的调用。完全没问题,但延迟是这里的主要问题。
任何人都可以为此问题推荐任何其他解决方案吗? Azure中有什么适合这个吗?
非常感谢
答案 0 :(得分:13)
首先 - 阐明你在"实时","同步/异步"之间的区别。 "单向/双向"。你排除的东西(队列和发布/订阅)当然可以用于双向请求/响应,但它们是异步的。
第二 - 澄清"效率" - 效率指标是多少?带宽?潜伏?开发时间?客户支持?
第三 - 意识到微服务的成本之一(延迟)是延迟。如果您在第一次整合时遇到问题,那么您可能会走很长的路。
我可以在主API和其他微服务API之间进行通信的不同方式是什么?每种方法的优缺点是什么?
脱离我的头顶:
当我们将多个应用程序绑在一起时,您会注意到这是相同的列表...因为这是您正在做的事情。只是因为你使应用程序更小并没有真正改变很多,除非你的系统甚至更多分布。期待解决所有相同的问题"正常"分布式系统,以及一些与部署和版本控制相关的额外系统。
考虑来自用户的幂等GET请求,例如"给我一个问题1"。该客户端期望问题1的JSON响应。简单。在我预期的架构中,客户端会点击api.myapp.com,然后它会通过REST将调用代理发送到question-api.myapp.com(微服务)以获取数据,然后返回给用户。我们怎么能在这里使用pub / sub?谁是发布者,谁是订阅者?这里没有事件要提出来。我对队列的理解:一个出版商,一个消费者。发布/子主题:一个发布者,许多消费者。谁在这里?
好的 - 首先,如果我们谈论微服务和延迟 - 我们需要一个更具代表性的例子。我们说我们的客户端是Netflix移动应用程序,要显示开始屏幕,它需要以下信息:
其中每一个都是由不同的微服务提供的(我们称之为M1-M5)。来自客户的每次通话 - >数据中心有100毫秒的预期延迟;服务之间的呼叫延迟为20ms。
让我们比较一些方法:
正如预期的那样,这是最低延迟选项 - 但需要整体服务中的所有内容,我们已经决定因运营问题而不愿意这样做。
那是500ms。使用具有此功能的代理无法提供帮助 - 它只会为每个请求添加20毫秒的延迟(使其达到600毫秒)。我们有1 + 2和4,以及3和5之间的依赖关系,但可以做一些异步。让我们看看它有何帮助。
我们降到200毫秒;还不错 - 但我们的客户需要了解我们的微服务架构。如果我们用我们的代理抽象它,那么我们有:
低至140毫秒,因为我们正在利用减少的服务内延迟。
很好 - 当事情顺利进行时,与单片(#1)相比,我们的延迟仅增加了40%。
但是,与任何分布式系统一样,我们也不得不担心事情进展顺利。
当M4的延迟增加到200毫秒时会发生什么?好吧,在客户端 - >异步微服务路由(#3),然后我们有100ms(第一批请求)的部分页面结果,200ms内不可用,400ms内的摘要。在代理案例(#4)中,我们没有任何东西,直到340ms。如果微服务完全不可用,也需要考虑类似因素。
队列是一种在空间和时间中抽象生产者/消费者的方式。让我们看看如果我们介绍一个会发生什么:
我们的客户,订阅了P2 - 接收到单个请求的部分结果,并从M1 + M2和M4以及M3和M5之间的工作流程中抽象出来。我们在最佳情况下的延迟是140ms,与#4相同,在最坏的情况下类似于直接客户端路由(#3)w /部分结果。
我们有一个更复杂的内部路由系统,但已经获得了微服务的灵活性,同时最大限度地减少了不可避免的延迟。我们的客户端代码也更复杂 - 因为它必须处理部分结果 - 但类似于异步微服务路由。我们的微服务通常彼此独立 - 它们可以独立扩展,并且没有中央协调权限(如代理案例中)。我们可以根据需要添加新服务,只需订阅相应的渠道,让客户知道如何处理我们生成的响应(如果我们生成一个用于客户端消费的话)。
您可以使用网关进行变体聚合响应,同时仍在内部使用队列。外观看起来很像#4,内部看起来很#5。添加一个队列(是的,我一直在使用队列,发布/订阅,主题等可互换)仍然将网关与各个微服务分离,但是从客户端抽象出部分结果问题(沿着w) /它的好处,但是)。
但是,添加网关可以让您集中处理部分结果问题 - 如果它在多个平台上复杂,不断变化和/或重新实现,则非常有用。
例如,让我们说,如果M4(摘要服务)不可用 - 我们有一个M4b对缓存数据进行操作(例如,星级评定已过期) 。 M4b可以立即应答R4a和R4b,然后我们的网关可以确定是否应该等待M4应答或者根据超时时间等待M4b。
有关Netflix 实际如何解决此问题的详细信息,请查看以下资源:
答案 1 :(得分:2)
Apache Thrift旨在高效沟通。它由Facebook(现在是开源)开发,实现是available for C#。
Google developed高效的protocol buffers序列化机制。协议缓冲区不包括RPC(远程过程调用),但可用于通过各种传输机制发送数据。它也是available for C#(SO自己的Marc Gravell项目)。
答案 2 :(得分:2)
首先,我建议将单片REST服务分解为多个微服务,每个服务都针对单个数据实体或用例。例如:发送电子邮件将是一个用例,查询搜索页面的结果将是一个用例。
然后,当您推出每个服务时,您可以修改单片服务以成为新微服务的代理。这样,您现有的应用程序可以继续调用您的单一服务,新的应用程序更新可以适当地调用微服务。
基本上,逐步从一个单一的服务迁移到微服务,一次一个。
想到的唯一方法是简单的基于REST的调用。完全没问题,但延迟是这里的主要问题。
使用单片Web服务作为微服务的代理会增加一些延迟,但单个微服务不会增加任何延迟,您可以将这些扩展到Azure后面的尽可能多的托管实例根据需要加载均衡器。
如果您确实看到了查询延迟,那么您可以为任何显示查询性能问题的微服务实现类似Redis缓存的功能。
如果您确实看到写入延迟成为问题,那么我建议移动这些问题写入以使用某种消息队列,以允许在可能的情况下异步处理它们。
Azure中有什么适合这个吗?
您可能需要查看Azure API Apps,因为它们可能提供一些很好的功能,可以通过Azure更轻松地保护/验证您的微服务,而不是单独保护。
我可以在主API与其他微服务API之间进行通信的不同方式是什么?
听起来你需要服务之间的实时通信。因此,除非您有可以在后台执行的任务,否则消息队列是不可能的。您可以在服务之间使用简单的REST调用,如果使用WCF实现,甚至可以使用SOAP之类的调用。虽然,听起来你现在正在使用REST,所以保持它是一样的。
此外,请确保您的微服务不通过数据库相互通信,因为这可能会很快变得混乱。使用简单的REST端点进行通信,类似于客户端应用程序使用的REST端点。
我喜欢遵循KISS(Keep It Simple Stupid)原则,因此我建议您尽量不要过度设计解决方案,并尽量保持简单。
答案 3 :(得分:1)
Azure中有什么适合这个吗?
Azure中还有另一种解决微服务方法的解决方案,我认为这种解决方案会引起很大的关注,称为Service Fabric。
这里的问题是你有一个现有的应用程序,并且使它适应Service Fabric可能要困难得多,但它当然值得一看。
Here you can find a Service Fabric example of a web service.
希望这有帮助!
祝你好运!