背景(您可以跳过此部分)
我有大量数据(大约 3 mb)需要在数百台机器上保持最新。有些机器运行 C#,有些运行 Java。数据可能随时更改,需要在几分钟内传播给客户端。数据以 Json 格式从 4 个负载平衡服务器传送。这 4 台服务器运行带有 Mvc 3 和 C# 4.0 的 ASP.NET 4.0。
在 4 个服务器上运行的代码有一个散列算法,该算法对 Json 响应进行散列,然后将散列转换为字符串。这个哈希是给客户端的。然后,每隔几分钟,客户端会使用哈希 ping 服务器,如果哈希过期,则返回新的 Json 对象。如果散列仍然是当前的,则返回带有空正文的 304。
有时 4 个框生成的哈希值在各个框之间不一致,这意味着客户端不断下载数据(每个请求可能会访问不同的服务器)。
代码片段
这是用于生成哈希的代码。
internal static HashAlgorithm Hasher { get; set; }
...
Hasher = new SHA1Managed();
...
Convert.ToBase64String(Hasher.ComputeHash(Encoding.ASCII.GetBytes(jsonString)));
为了尝试调试问题,我将其拆分如下:
Prehash = PreHashBuilder.ToString();
ASCIIBytes = Encoding.ASCII.GetBytes(Prehash);
HashedBytes = Hasher.ComputeHash(ASCIIBytes);
Hash = Convert.ToBase64String(HashedBytes);
然后我添加了一条吐出上述值的路线,并使用 Beyond Compare 来比较差异。
字节数组被转换为字符串格式以供 BeyondCompare 使用,方法是使用:
private static string GetString(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in bytes)
{
sb.Append(b);
}
return sb.ToString();
}
如您所见,字节数组按字面意思显示为字节序列。它没有被“转换”。
问题
我发现 Prehash 和 ASCIIBytes 的值是相同的,但是 HashedBytes 的值是不同的——这意味着 Hash 也是不同的。
我在 4 个服务器上重启了 IIS 网站几次,当它们有不同的哈希值时,比较了 BeyondCompare 中的值。在任何情况下,都是“HashedBytes”值不同(SHA1Managed.ComputeHash(...) 的结果)
问题
我究竟做错了什么?ComputeHash 函数的输入是相同的。SHA1Managed 机器是否依赖?这不会因为 4 台机器有一半的时间具有相同的哈希值。
我搜索了 StackOverFlow 和 Bing,但找不到其他有此问题的人。我能找到的最接近的是编码有问题的人,但我想我已经证明编码不是问题。
输出
我希望不要因为时间太长而将所有内容都倾倒在这里,但这是我正在比较的转储的片段:
哈希:o1ZxBaVuU6OhE6De96wJXUvmz3M=
HashedBytes:163861135165110831631611916022224717299375230207115
ASCIIBytes:.... Prehash:...
当我比较不同服务器上的两个页面时,ASCII 字节是相同的,但 HashedBytes 不是。我用于字节的转储方法不进行任何转换,它只是按顺序转储每个字节。我可以用“。”分隔字节。我想。
跟进 我已更改 b.ToString(CultureInfo.InvariantCulture) 并将 HashAlgorithm 设为局部变量而不是静态属性。我正在等待代码部署到服务器。