Фон
Я использую библиотеку Apache NMS для общения с ActiveMq. Каждое отправленное сообщение имеет метку времени от производителя, я смотрю на задержку сообщения, вычитая временную метку из DateTime.UtcNow
, я ожидаю увидеть задержки 0-100 мс, но вместо этого я вижу, что задержки составляют от -1000 до 1000 Миз. Очевидно, что отрицательные задержки не имеют смысла, поэтому я изначально подозревал, что системные часы не синхронизированы, однако теперь я независимо подтвердил, что они правильные и находятся в пределах 20 мс друг от друга.
Больше фона
Измерение задержки широковещательного сообщения с использованием системных часов, хорошая идея?
Вопрос
Теперь я считаю, что расхождения могут быть связаны с тем, как обрабатываются даты в .Net и Java.
- Потеряно ли преобразование из Java в / из .Net раз?
- Могут ли преобразования объяснить большие отрицательные промежутки времени, которые я наблюдал?
- Есть ли что-то еще, что могло бы объяснить разницу во времени?
MessageProducer.cs -
Производитель наборов NMSTimestamp
activeMessage.NMSTimestamp = DateTime.UtcNow;
ActiveMqMessage.cs -
NMSTimestamp преобразует время Java и сохраняет в сообщении
...
public DateTime NMSTimestamp
{
get { return DateUtils.ToDateTime(Timestamp); }
set
{
Timestamp = DateUtils.ToJavaTimeUtc(value);
if(timeToLive.TotalMilliseconds > 0)
{
Expiration = Timestamp + (long) timeToLive.TotalMilliseconds;
}
}
}
...
Message.cs -
Временная метка содержит дату в формате проводника, маршаллер сообщения устанавливает это значение напрямую
// ActiveMqMessage extends Message
...
public long Timestamp
{
get { return timestamp; }
set { this.timestamp = value; }
}
...
DateUtils.cs -
Используется для выполнения преобразований
namespace Apache.NMS.Util
{
public class DateUtils
{
/// <summary>
/// The start of the Windows epoch
/// </summary>
public static readonly DateTime windowsEpoch = new DateTime(1601, 1, 1, 0, 0, 0, 0);
/// <summary>
/// The start of the Java epoch
/// </summary>
public static readonly DateTime javaEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);
/// <summary>
/// The difference between the Windows epoch and the Java epoch
/// in milliseconds.
/// </summary>
public static readonly long epochDiff; /* = 1164447360000L; */
static DateUtils()
{
epochDiff = (javaEpoch.ToFileTimeUtc() - windowsEpoch.ToFileTimeUtc())
/ TimeSpan.TicksPerMillisecond;
}
public static long ToJavaTime(DateTime dateTime)
{
return (dateTime.ToFileTime() / TimeSpan.TicksPerMillisecond) - epochDiff;
}
public static DateTime ToDateTime(long javaTime)
{
return DateTime.FromFileTime((javaTime + epochDiff) * TimeSpan.TicksPerMillisecond);
}
public static long ToJavaTimeUtc(DateTime dateTime)
{
return (dateTime.ToFileTimeUtc() / TimeSpan.TicksPerMillisecond) - epochDiff;
}
public static DateTime ToDateTimeUtc(long javaTime)
{
return DateTime.FromFileTimeUtc((javaTime + epochDiff) * TimeSpan.TicksPerMillisecond);
}
}
}
Мой код рассчитывает задержку следующим образом
var latency = (DateTime.UtcNow - msg.NMSTimestamp).TotalMilliseconds;