背景(您可以跳过本节)
我有大量的数据(约3 MB),需要在数百台机器上保持最新状态。一些机器运行C#,一些运行Java。数据随时可能发生变化,并且需要在几分钟内传播到客户端。数据以Json格式从4个负载平衡服务器传递。这4个服务器使用ASP.NET 4.0,Mvc 3和C# 4.0运行。
在4个服务器上运行的代码具有散列算法,该算法对Json响应进行散列,然后将散列转换为字符串。此哈希值提供给客户端。然后,每隔几分钟,客户端会发送带有哈希的请求到服务器,如果哈希已过期,则返回新的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值不同,这意味着哈希也不同。
我多次重启了4台服务器上的IIS网站,并在它们具有不同哈希值时使用BeyondCompare比较了数值。在每种情况下都有一个不同的"HashedBytes"值(即SHA1Managed.ComputeHash(...)的结果)。
问题是什么?ComputeHash函数的输入是相同的。SHA1Managed是否与机器相关?那不太可能,因为四台机器有一半的时间具有相同的哈希值。
我已经在StackOverFlow和Bing上搜索过,但未能找到其他人有此问题。我能找到的最接近的问题是编码问题,但我认为我已经证明了编码并不是问题。
输出:
由于内容较长,我希望不要全部展示,但是以下是我正在比较的片段:
哈希:o1ZxBaVuU6OhE6De96wJXUvmz3M=
哈希字节:163861135165110831631611916022224717299375230207115
ASCII字节:1151169710310146991111094779114100101114831011141181059910147115101114118105991014611511899591151051031101171129511510111411810599101114101102101114101110991011159598979910710111010011111410010111411510111411810599101951185095117114108611041161161125847471051159897991071011101004610910211598101115116971031014699111109477911410010111483101114118105991014711510111411810599101461151189947118505911510510311011711295115101114118105991011141011021011141011109910111595989799107101110100112971211091011101161151161111141011151011141.... Prehash:... 当我在不同的服务器上比较这两个页面时,ASCII字节相同,但HashedBytes不同。我用于字节转储的方法不进行任何转换,只是连续地将每个字节转储出来。我可以用"."分隔字节。
跟进:
我已对代码进行了更改,将b.ToString(CultureInfo.InvariantCulture)和HashAlgorithm更改为本地变量而不是静态属性。 我正在等待代码部署到服务器。
ASCIIBytes
字节相同,你是怎么确定的? - MagnusSequenceEqual
来比较数组:var areSame = bytes1.SequenceEqual(bytes2);
不需要转换为字符串。 - Magnus