我有一个kubernetes群集,我打算在吊舱中实现服务 - 该服务将接受GRPC请求,开始长期运行的过程,但返回到呼叫者,以表明该过程已经启动。调查表明, iHostedService
( backgroundService
)是这样做的方法。
我的问题是,将使用 backgroundService
与ASP.NET和K8S的各种整洁功能表现得很好:
- 将水平缩放理解,即使该服务将出现,服务即使将出现,服务都将过载并旋转新实例由于所有工作都是背景(我感谢可以实现的挂钩,我想知道默认行为是什么),
-
等待
互换了,另一个与背景服务的运行正常(我只在收到一条消息的情况下经历了等待
,因此可以处理另一条消息,但是背景服务不是消息传递上下文
- ) ASP.NET通常会管理限制太多请求,如果服务器太忙,请备份,但是如果“忙碌”是背景过程,则该请求仍然有效,
- 这是减轻超载服务的最佳方法(如果水平扩展为不是一个选项) - 我可以将GRPC调用reutrn“太忙”,但需要检测到它(不确定这是CPU绑定,内存还是仅仅是背景服务的数量),
- 我是否应该考虑除
backgroundServiceServiceserviceserviceserviceserviceserviceserviceservices服务。
对于此任务,
我希望答案是“一切都起作用”,但要确认它比希望...确认更好...
I have a kubernetes cluster into which I'm intending to implement a service in a pod - the service will accept a grpc request, start a long running process but return to the caller indicating the process has started. Investigation suggests that IHostedService
(BackgroundService
) is the way to go for this.
My question is, will use of BackgroundService
behave nicely with various neat features of asp.net and k8s:
- Will horizontal scaling understand that a service is getting overloaded and spin up a new instance even though the service will appear to have no pending grpc requests because all the work is background (I appreciate there's probably hooks that can be implemented, I'm wondering what's default behaviour)
- Will the notion of
await
ing allowing the current process to be swapped out and another run work okay with background services (I've only experienced it where one message received hits an await
so allows another message to be processed, but backround services are not a messaging context)
- I think asp.net will normally manage throttling too many requests, backing off if the server is too busy, but will any of that still work if the 'busy' is background processes
- What's the best method to mitigate against overloading the service (if horizontal scaling is not an option) - I can have the grpc call reutrn 'too busy' but would need to detect it (not quite sure if that's cpu bound, memory or just number of background services)
- Should I be considering something other than
BackgroundService
for this task
I'm hoping the answer is that "it all just works" but feel it's better to have that confirmed than to just hope...
发布评论
评论(2)
i 强烈推荐带有单独的背景服务队列。分为两个图像,一个运行ASP.NET GRPC请求,另一个处理耐用队列的图像并不难(这可以是控制台应用程序 - 请参见VS中的服务工作者模板)。请注意,使用 non 的解决方案是不可靠的(即,每当pod重新启动或缩放时,工作可能会丢失)。这包括内存的队列,通常建议将其作为“解决方案”。
如果您确实在控制台应用程序中制作自己的背景服务,建议您应用几个调整(在我的博客上注明):
executeasync
intask.run
。executeasync
中尝试/catch
。ihostapplicationlifetime.stopapplication
出于任何原因停止时。我更喜欢使用两个不同图像的原因之一是它们可以在不同的触发器上扩展:GRPC请求API和对工作人员的排队消息。根据您的队列,使用“排队消息”作为触发器可能需要自定义公制提供商。我确实更喜欢使用“排队消息”,因为它是工人形象的自然缩放机制。诸如CPU使用之类的开箱即用解决方案并不总是很好地工作 - 特别是对于您正在使用的异步处理器而言。
背景服务可以是异步的,而不会出现任何问题。实际上,批次获取消息并同时处理它们并不少见。
编号ASP.NET只有节气门请求,则该请求仍然有效。背景服务确实在ASP.NET上注册,但这仅是 在优雅的关闭时提供最佳效果。 ASP.NET不知道背景服务有多忙,在待处理的队列项目,CPU使用或即将发出的请求方面。
如果您使用耐用的队列 +独立的工作图像解决方案,则不是问题。 GRPC呼叫几乎总是可以在队列中添加另一个消息(非常简单且快速),并且K8可以根据您(可能是自定义的)“出色的队列消息”的指标自动估算。
I strongly recommend using a durable queue with a separate background service. It's not that difficult to split into two images, one running ASP.NET GRPC requests, and the other processing the durable queue (this can be a console app - see the Service Worker template in VS). Note that solutions using non-durable queues are not reliable (i.e., work may be lost whenever a pod restarts or is scaled down). This includes in-memory queues, which are commonly suggested as a "solution".
If you do make your own background service in a console app, I recommend applying a few tweaks (noted on my blog):
ExecuteAsync
inTask.Run
.try
/catch
inExecuteAsync
.IHostApplicationLifetime.StopApplication
when the background service stops for any reason.One reason I prefer using two different images is that they can scale on different triggers: GRPC requests for the API and queued messages for the worker. Depending on your queue, using "queued messages" as the trigger may require a custom metric provider. I do prefer using "queued messages" because it's a natural scaling mechanism for the worker image; out-of-the-box solutions like CPU usage don't always work well - in particular for asynchronous processors, which you mention you are using.
Background services can be asynchronous without any problems. In fact, it's not uncommon to grab messages in batches and process them all concurrently.
No. ASP.NET only throttles requests. Background services do register with ASP.NET, but that is only to provide a best-effort at graceful shutdown. ASP.NET has no idea how busy the background services are, in terms of pending queue items, CPU usage, or outgoing requests.
Not a problem if you use the durable queue + independent worker image solution. GRPC calls can pretty much always stick another message in the queue (very simple and fast), and K8 can autoscale based on your (possibly custom) metric of "outstanding queue messages".
通常,“一切都起作用”。
对于自动水平尺度,您需要一个自动制剂,请阅读以下内容:
但是您可以自己扩展(
kubectl量表部署您的删除 - replicas = 10
)。假设您将部署后端,这将从一个POD开始。您的Autoscaler会观看您的吊舱(例如使用CPU),并在您的负载高时为您启动一个新的豆荚。
将开始第二个吊舱。每个新请求都会发送到不同的POD(圆形旋转)。
没有必要,您的后端油门通话。它应该尽可能处理许多电话。
Generally, "it all works".
For the automatic horizontal scale, you need a autoscaler, read this: Horizontal Pod Autoscale
But you can just scale it yourself (
kubectl scale deployment yourDeployment --replicas=10
).Lets assume, you have a deployment of your backend, which will start with one pod. Your autoscaler will watch your pod (eg. used cpu) and will start a new pod for you, when you have a high load.
A second pod will be started. Each new request will send to different pods (round-robin).
There is no need, that your backend throttle calls. It should just handle many calls as possible.