如何基于特定资源路径执行尽可能公平的负载平衡

时间:2011-08-15 21:54:15

标签: java ruby performance redis load-balancing

我有一个应用程序从文件(PDF文件中的页面作为图像)提供工件,原始PDF文件存在于S3上,当客户端点击其中一个时,它们会下载到生成图像的服务器上。这些机器具有本地缓存​​机制,可确保每个PDF文件只下载一次。

因此,当客户提出请求给我第1页pdf 123.pdf 时,会检查此缓存,如果其中没有pdf文件,则从S3下载并存储在本地缓存然后进程生成此页面1并将图像发送回客户端。

客户端本身并不知道它连接到一个特殊的服务器,它看起来只是访问网站服务器,但是,为了性能,我想确保这个客户端总是被定向到提供第一次请求的同一文件服务器(并从S3下载文件)。

我可以在客户端设置一个cookie,让他总是从那个特定的文件服务器上下载,但是把它放在客户端会导致不公平的使用,因为有些用户要打开很多文件而有些用户不是这样我想在资源级别执行此负载平衡(PDF文档)。

每个文档都有一个唯一的标识(数据库中的整数主键),我的第一个解决方案是使用Redis并将文档ID存储为键,值是当前缓存此文档的服务器计算机的主机,但是我想删除Redis或寻找一种更简单的方法来实现它,而不需要在其他地方查找密钥。

此外,如果定义的算法或想法允许动态添加更多文件服务器,那将是很好的。

基于资源以亲和力执行此类负载平衡的最佳方法是什么?

仅仅是为了说,这个应用程序是Ruby,java和Scala的混合。

1 个答案:

答案 0 :(得分:2)

我在负载均衡器中使用以下方法:

  • 删除请求的资源URL以删除查询和片段部分。
  • 将剥离的URL转换为字符串并获取其哈希码。
  • 使用哈希码从可用服务器列表中选择后端服务器; e.g。

    String[] serverNames = ...
    String serverName = serverNames[hash % serverNames.length];
    

这会将负载均匀地分布在所有服务器上,并始终将相同的请求发送到同一服务器。如果您添加更多服务器,它会自行调整...虽然您在缓存再次升温时会受到性能影响。

我认为你不想以“公平”为目标;即某种保证每个请求大致需要相同的时间。为了实现公平,您需要主动监控每个后端的负载并根据负载进行调度。这将(有些)否定缓存/亲和力,并将消耗资源来进行测量和负载平衡决策。一个愚蠢的负载传播方法(例如我的建议)应该为您的用例提供更好的吞吐量。