当前位置: 首页 > 知识库问答 >
问题:

在多个。NET应用程序之间进行通信的最有效方法

钱志强
2023-03-14

目前我有一个设置,我的客户机(web应用程序,iOS应用程序等)通过REST调用与我的后端API.NET web应用程序(Nancy)对话。没什么特别的.

我现在需要将这个API拆分为微服务,每个服务可以单独升级/部署。

我的主API(公共)将只执行身份验证,然后调用我的一个微服务,它将在我的专用网络中。

在主API和其他微服务API之间有哪些不同的通信方式?每种方法的优点/缺点?

通信需要是实时的--例如,请求来自浏览器/设备,主API执行auth,然后调用微服务API,然后返回响应。所以我不能使用队列或pub/sub之类的东西。它不一定需要使用HTTP,但需要实时通信(请求/响应)。我还有其他服务(WebJobs、云服务等)需要与这些微服务(它们也在专用网络中)对话。

想到的唯一方法是简单的基于REST的调用。完全可以,但是延迟是这里的主要问题。

有人能推荐其他解决这个问题的办法吗?天蓝有什么适合这个的吗?

多谢

共有1个答案

孙永嘉
2023-03-14

首先--澄清“实时”、“同步/异步”和“单向/双向”之间的区别。您排除的东西(队列和pub/sub)当然可以用于双向请求/响应,但它们是异步的。

第二--澄清“效率”--效率的衡量标准是什么?带宽?潜伏期?开发时间?客户支持?

第三,意识到微服务的成本之一是延迟。如果这是您在第一次集成时遇到的一个问题,那么您可能会有很长的路要走。

在主API和其他微服务API之间有哪些不同的通信方式?每种方法的优点/缺点?

在我的脑海中:

  • 单节点主机和IPC:优点:性能;缺点:与部署拓扑紧密耦合;对其他节点的可达性;客户支助;故障模式
  • Rest/肥皂/等。endpoint:优点:广泛的客户端和服务器支持;调试;web缓存,缺点:性能;故障模式
  • 二进制协议:优点:性能;缺点:版本化;客户机和服务器支持;调试;故障模式
  • 消息队列:优点:异步性;缺点:复杂性
  • ESB:PROS:异步性;客户支助;缺点:复杂性
  • 平面文件:优点:带宽;简单;客户支助;缺点:潜伏期,一般PITA

您会注意到,当我们将多个应用程序绑定在一起时,这是相同的列表...因为这就是您正在做的。仅仅因为你使应用程序变小并没有真正的改变,除了使你的系统更加分布式之外。期望解决“普通”分布式系统所面临的所有相同问题,以及一些与部署和版本控制有关的额外问题。

考虑一个来自用户的幂等GET请求,比如“GET me Question1”。该客户机期望问题1的JSON响应。很简单。在我预期的体系结构中,客户机将访问api.myapp.com,然后通过REST代理调用Question-api.myapp.com(微服务)以获取数据,然后返回给用户。我们怎么能在这里使用酒吧/潜艇?谁是发布者,谁是订阅者?这里没有事件要提。我对队列的理解:一个发布者,一个消费者。酒吧/子主题:一个出版商,许多消费者。这里谁是谁?

好的--所以首先,如果我们讨论微服务和延迟--我们需要一个更有代表性的例子。假设我们的客户端是Netflix移动应用程序,要显示打开的屏幕,它需要以下信息:

  1. 流行电影ID列表
  2. 最近观看的电影ID列表
  3. 帐户状态
  4. 对于所引用的每个电影id:name、#明星、摘要文本
  5. 您所在地区不可用的电影ID列表(要从趋势/最近观看的电影中筛选出来)

其中的每一个都由不同的微服务提供(我们称之为M1-M5)。来自客户机->数据中心的每个调用具有100ms的预期延迟;服务之间的呼叫有20ms的延迟。

让我们比较几种方法:

  1. t0+100ms:客户端发送/api//startscreen请求;接收响应

不出所料,这是最低延迟的选项--但需要一个整体服务中的所有内容,出于操作考虑,我们决定不希望这样做。

    null

就是500毫秒。使用代理W/,这是没有帮助的--它只会给每个请求增加20ms的延迟(使其达到600ms)。我们在1+2和4以及3和5之间有一个依赖关系,但可以执行一些异步操作。让我们看看这有什么帮助。

  1. T0:客户端向M1/API/Trending发送请求
  2. T0:客户端向M2/API//最近发送请求
  3. T0:客户端向M3/API//Account发送请求
  4. T0+200ms:(来自1+2的响应)客户端向M4/API/Summary发送请求?movieids=[]
  5. T0+200ms:(来自3的响应)客户端向M5/API//不可用发送请求

我们下降到200毫秒;不错--但是我们的客户需要了解我们的微服务架构。如果我们用代理抽象它,那么我们有:

  1. T0+100ms:客户端向G1/api/startscreen发送请求
  2. T1:G1向M1/API/Trending发送请求
  3. T1:G1向M2/API//最近发送请求
  4. T1:G1向M3/API//Account发送请求
  5. T1+40ms:(1+2的响应)G1向M4/API/Summary发送请求?movieids=[]
  6. T1+40ms:(来自3的响应)G1向M5/API//不可用发送请求

降低到140ms,因为我们利用了减少的服务内延迟。

很好--当工作顺利时,我们只比单片(#1)增加了40%的延迟。

但是,与任何分布式系统一样,我们也必须担心事情不顺利的时候。

  1. T0+100ms:客户端将请求Q0发布到P1 StartScreen,应答通道为P2
  2. T1+20ms:M1看到Q0,将响应R1置于P2趋势/Q0
  3. T1+20ms:M2看到Q0,将响应R2放到P2最近/Q0
  4. T1+20ms:M3看到Q0,将响应R3放到P2帐户/Q0
  5. T2+40ms:M4看到R1,将响应R4a放到P2摘要/Q0
  6. T2+40ms:M4看到R2,将响应R4b放到P2摘要/Q0
  7. T2+40ms:M5看到R3,将响应R5置入P2无效/Q0

我们的客户端订阅了P2-接收部分结果W/1个请求,并从M1+M2和M4以及M3和M5之间的工作流中抽象出来。我们的延迟在最好的情况下是140ms,与#4相同,在最坏的情况下类似于直接客户端路由(#3)w/部分结果。

我们有一个复杂得多的内部路由系统,但已经获得了灵活性/微服务,同时将不可避免的延迟最小化。我们的客户机代码也更复杂--因为它必须处理部分结果--但类似于异步微服务路由。我们的微服务通常是相互独立的--它们可以独立地伸缩,并且没有中央协调机构(就像代理的情况一样)。我们可以根据需要添加新的服务,只需订阅适当的通道,并让客户机知道如何处理我们生成的响应(当然,如果我们生成一个供客户机使用)。

您可以使用网关聚合响应,同时仍然在内部使用队列。它在外部看起来很像#4,但在内部看起来很像#5。队列的添加(是的,我一直在使用queue、pub/sub、topic等,可以互换)仍然将网关与单个微服务解耦,但从客户机中抽象出部分结果问题(尽管有其优点)。

不过,网关的添加确实允许您集中处理部分结果问题--如果它复杂、不断变化和/或跨多个平台重新实现,则非常有用。

例如,假设在M4(摘要服务)不可用的情况下,我们有一个M4b对缓存的数据进行操作(例如,星级已经过时)。M4b可以立即回答R4a和R4b,然后我们的网关可以根据超时确定它是应该等待M4回答还是只进行W/M4b。

有关Netflix如何实际解决这个问题的进一步信息,请参阅以下资源:

  1. 他们的API网关
  2. 容错层基础上的消息传递模式
  3. 有关微服务中的IPC的详细信息
 类似资料:
  • 问题内容: 我是程序世界中的每个新手,我遇到一个问题,我的要求与使用JAVA Code在Android平板电脑与台式机之间的通信有关。 上面的代码是我的servlet代码,它在我的本地系统服务器(Tomcat 6.0)中运行,在这里,我正在通过println发送消息,并且我想在另一个系统中运行的Android应用中显示相同的消息。现在,我要发布在另一个系统上运行的android代码。 这里的192

  • 本文向大家介绍Android多进程间采用AIDL方式进行通信,包括了Android多进程间采用AIDL方式进行通信的使用技巧和注意事项,需要的朋友参考一下 在上一节中,我介绍了Android中Service的生命周期以及一些有关知识。在这一节中,我采用代码编写的方式来介绍一下不同程序之间也就是不同进程之间通信采用AIDL方式。 首先我需要解释一下,不同程序进程间采用AIDL方式启动服务,我们可以看

  • 问题内容: 问题是: 假设我们有两个正在运行的Node.js进程:和。 结果中有返回的函数。 是否有一种从内部调用并获得结果的方法? 从我对Node.js的了解中,我仅找到一种使用套接字进行通信的解决方案。但是,这不是理想的,因为它将需要一个进程在端口上侦听。如果可能,我希望避免这种情况。 编辑: 经过一些问题,我很想补充一点,在层次结构中不能是的子进程,而恰恰相反。同样,如果有帮助,则只能有一个

  • 我有一个扩展JPanel的类“GUI”。我有另一个扩展JFrame的类“Buttons”。我试图让JFrame类调用JPanel类中的方法“clearscreen()”,当在JFrame上按下JButton“clearb”时。实现这一工作的唯一方法是在JButton的actionlistener中为JPanel类“GUI”构建对象: 但是当我调用方法clearScreen()时,它看起来如下所示:

  • 问题内容: 我正在用Go编写负载平衡的服务器系统。 负载平衡服务器将与多个应用程序服务器通信并处理请求。这些服务器都可以在同一台计算机或网络上运行。 我已经找到了网络,但是现在我需要找到一种最佳的方式来使负载均衡器与本地应用程序服务器进行通信。使用-networking似乎并非最佳选择。 我正在尝试通过和系统调用共享内存,但是没有找到任何有效的示例,并且该软件包也完全没有文档说明。 有人可以为我提

  • 如何在同一台服务器上独立运行多个web应用程序? docker是正确的方法(请举例说明)还是矫枉过正? 有没有其他选择我应该考虑? 我还需要考虑其他问题(潜在问题、解决方案)吗?