我在调用StackExchange.Redis时遇到了死锁情况.
我不确切知道发生了什么,这是非常令人沮丧的,我希望任何有助于解决或解决此问题的输入.
万一你也有这个问题,不想读这一切; 我建议你将尝试设置
PreserveAsyncOrder
到false
.Run Code Online (Sandbox Code Playgroud)ConnectionMultiplexer connection = ...; connection.PreserveAsyncOrder = false;
这样做可能会解决此Q&A所涉及的僵局,并且还可以提高性能.
await
和Wait()
/ Result
).当应用程序/服务启动时,它会正常运行一段时间,然后突然(几乎)所有传入的请求都会停止运行,它们永远不会产生响应.所有这些请求都在等待Redis完成呼叫的死锁.
有趣的是,一旦发生死锁,对Redis的任何调用都将挂起,但前提是这些调用是来自传入的API请求,这些调用是在线程池上运行的.
我们还从低优先级后台线程调用Redis,这些调用即使在发生死锁后也会继续运行.
似乎只有在线程池线程上调用Redis时才会出现死锁.我不再认为这是因为这些调用是在线程池线程上进行的.相反,似乎任何异步Redis调用没有延续,或者同步安全延续,即使在发生死锁情况后也会继续工作.(见下面我认为发生的事情)
混合引起的死锁await
和Task.Result
(像我们一样同步异步).但是我们的代码在没有同步上下文的情况下运行,因此这里不适用,对吧?
是的,我们不应该这样做.但我们这样做了,我们将不得不继续这样做一段时间.需要迁移到异步世界的大量代码.
同样,我们没有同步上下文,所以这不应该导致死锁,对吧?
ConfigureAwait(false)
在任何设置之前设置await
对此没有影响.
异步命令和Task.WhenAny等待StackExchange.Redis之后的超时异常
这是线程劫持问题.目前的情况如何?这可能是问题吗?
来自Marc的回答:
...混合等待和等待不是一个好主意.除了死锁之外,这是"同步异步" - 一种反模式.
但他也说:
SE.Redis在内部绕过sync-context(库代码正常),所以它不应该有死锁
因此,根据我的理解,StackExchange.Redis应该与我们是否使用同步异步 …
我需要定期备份Azure存储帐户中的所有blob和表,以便我们可以在以后因任何原因损坏我们的数据而还原所有数据.
虽然我相信我们存储在Azure中的数据是持久的并且在数据中心发生故障时可以恢复,但我们仍然需要备份存储帐户中的数据以防止意外覆盖和删除(人为错误因素).
我们为此实施了一个解决方案,定期列出所有blob并将其复制到备份存储帐户.修改或删除blob后,我们只需在备份帐户中创建旧版本的快照.
这种方法对我们有效.但它只处理blob,而不是表实体.我们现在也需要支持备份表实体.
现在面对这个任务,我想其他人可能之前已经有了这个要求并提出了一个智能解决方案.或者也许有商业产品可以做到这一点?
备份目标不是另一个Azure存储帐户.我们所需要的只是一种恢复所有blob和表的方法,就像我们运行备份时一样.
任何帮助表示赞赏!
我正在努力确保Windows服务程序(在.NET之上运行)正确释放其网络连接.
在本地运行服务时,我知道它将在端口57300上创建大量到localhost的HTTP连接.我用它netstat
来监视它们是否正确释放.
我很惊讶地发现这个端口的许多连接都归"系统空闲进程"(PID = 0)所有.
在这里我们可以看到服务程序只拥有其中三个连接(PID = 5012).所有其他人都归PID 0所有.
我的主要问题是:为什么会这样?而我需要照顾?
但我也想知道:
这是否意味着服务程序确实正确地释放了连接?
如果需要,这些连接会被重用吗?
在.NET ServicePointManager中进行这样的连接"保留插槽" 吗?
我最近将我的一个项目从.NET Core 2.0升级到.NET Core 2.1.这样做后,我的几个测试开始失败.
在缩小此范围之后,我发现在.NET Core 2.1中,使用带有文化感知的比较器和字符串排序比较选项来计算字符串的哈希码是不可能的.
我创建了一个可以重现我的问题的测试:
[TestMethod]
public void Can_compute_hash_code_using_invariant_string_sort_comparer()
{
var compareInfo = CultureInfo.InvariantCulture.CompareInfo;
var stringComparer = compareInfo.GetStringComparer(CompareOptions.StringSort);
stringComparer.GetHashCode("test"); // should not throw!
}
Run Code Online (Sandbox Code Playgroud)
我在几个框架上测试了它,结果如下:
失败的时候ArgumentException
会CompareInfo.GetHashCodeOfString
说:
标志的值无效
现在,我的问题:
为什么CompareOptions.StringSort
在计算哈希码时不允许使用它?
为什么在.NET Core 2.0中允许它?`
据我所知,CompareOptions.StringSort
只影响字符串的相对排序顺序,不应影响哈希码计算.MSDN说:
StringSort指示字符串比较必须使用字符串排序算法.在字符串排序中,连字符和撇号以及其他非字母数字符号位于字母数字字符之前.
在程序中,我使用dynamic
关键字来调用最佳匹配方法.但是,我发现框架StackOverflowException
在某些情况下会崩溃.
我试图尽可能地简化我的代码,同时仍能够重新产生这个问题.
class Program
{
static void Main(string[] args)
{
var obj = new SetTree<int>();
var dyn = (dynamic)obj;
Program.Print(dyn); // throws StackOverflowException!!
// Note: this works just fine for 'everything else' but my SetTree<T>
}
static void Print(object obj)
{
Console.WriteLine("object");
}
static void Print<TKey>(ISortedSet<TKey> obj)
{
Console.WriteLine("set");
}
}
Run Code Online (Sandbox Code Playgroud)
如果新建的实例实现了接口并打印了"对象",则该程序通常会打印"set" ISortedSet<TKey>
.但是,通过以下声明,将StackOverflowException
抛出a (如上面的注释中所述).
interface ISortedSet<TKey> { }
sealed class SetTree<TKey> : BalancedTree<SetTreeNode<TKey>>, ISortedSet<TKey> {}
abstract class BalancedTree<TNode>
where TNode : …
Run Code Online (Sandbox Code Playgroud) <label for="input">Label</label><input type="file" id="input"/>
Run Code Online (Sandbox Code Playgroud)
在Firefox 7中,无法通过单击标签来触发打开的文件对话框.
这个问题非常相似,但是用绿色检查它是FF中的一个错误.我正在寻找一种解决方法.
有任何想法吗?
我正在尝试DELETE
使用jQuery从Chrome 发送跨域请求.
但是,在开发人员控制台中记录以下错误消息时失败:
XMLHttpRequest无法加载
http://actual/url/here
.Access-Control-Allow-Methods不允许使用DELETE方法.
javascript代码在localhost上运行,如下所示:
$.ajax({
type: "DELETE",
url: "http://actual/url/here",
xhrFields: {
withCredentials: true
}
});
Run Code Online (Sandbox Code Playgroud)
这会导致发送此类飞行前请求:
OPTIONS http://actual/url/here HTTP/1.1
Host: actual
Connection: keep-alive
Access-Control-Request-Method: DELETE
Origin: null
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36
Access-Control-Request-Headers: accept
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Run Code Online (Sandbox Code Playgroud)
响应看起来像这样:
HTTP/1.1 200 OK
Cache-Control: must-revalidate, private
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
Access-Control-Allow-Methods: DELETE GET HEAD POST PUT OPTIONS TRACE
Access-Control-Allow-Headers: accept
Access-Control-Max-Age: 900
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: …
Run Code Online (Sandbox Code Playgroud) FormatterServices.GetSerializableMembers为派生类型返回两次受保护和内部字段.曾经作为一个实例,SerializationFieldInfo
一次作为RtFieldInfo
.
我发现这很令人困惑!任何人都可以帮助我理解为什么微软决定以这种方式实现它?
我写了一个重新产生问题的示例程序:
class Program
{
[Serializable]
public class BaseA
{
private int privateField;
}
[Serializable]
public class DerivedA : BaseA { }
[Serializable]
public class BaseB
{
protected int protectedField;
}
[Serializable]
public class DerivedB : BaseB { }
static void Main(string[] args)
{
Program.PrintMemberInfo(typeof(DerivedA));
Program.PrintMemberInfo(typeof(DerivedB));
Console.ReadKey();
}
static void PrintMemberInfo(Type t)
{
Console.WriteLine(t.Name);
foreach (var mbr in FormatterServices.GetSerializableMembers(t))
{
Console.WriteLine(" {0} ({1})", mbr.Name, mbr.MetadataToken);
}
Console.WriteLine();
}
}
Run Code Online (Sandbox Code Playgroud)
我希望这一点,privateField
并protectedField
报告一次.但是这是运行程序时的实际输出: …
我有一个启动HTML5 SharedWorker
脚本的网页.每次重新加载此页面时,Chrome内存使用量都会增加(按F5键).
worker脚本非常简单.每秒(使用setInterval
)一条消息被发送到连接的端口.
似乎每次我按F5时终止并重新启动工作进程.这是我所期望的,因为工作人员实际上并没有被多个"文档"共享.但是,我无法弄清楚为什么每次刷新都会增加内存使用量.
有人知道为什么会这样吗?
鉴于每次重新加载页面时内存都会增加,这让我觉得我根本不能在Chrome中使用共享工作者.有没有人能够在没有记忆问题的情况下这样做?
UPDATE
这是托管HTML:
<div id="output"></div>
<script type="text/javascript" src="/scripts/jquery-1.4.4.js"></script>
<script type="text/javascript">
$(function () {
var worker = new SharedWorker("/scripts/worker.js")
worker.port.onmessage = function(e) {
$("#output").append($("<div></div>").text(e.data));
};
worker.port.start();
});
</script>
Run Code Online (Sandbox Code Playgroud)
......这是worker.js
:
var list = [];
setInterval(function () {
for (var i = 0; i < list.length; ++i) {
list[i].postMessage("#connections = " + list.length);
}
}, 1000);
onconnect = function (event) {
list.push(event.ports[0]);
};
Run Code Online (Sandbox Code Playgroud)
托管页面启动/连接到共享工作器并输出从其接收的任何内容.
工作代码保留已连接端口的列表,并每秒向它们发送一次消息.
这很简单.但是,每次在Chrome中重新加载托管页面时.该选项卡的内存负载增加.
以下显示了几次刷新后Chrome的内存使用情况:
......经过一些清新后,我达到了250 MB ......
我的想法已经不多了,认为这一定是Chrome中的一个错误.任何人都可以给我一些指针吗?
更新2
禁用我的AdBlock扩展程序似乎可以解决问题: …
在开发使用Redis的组件时,我发现它是一个很好的模式,可以为该组件使用的所有键添加前缀,这样它就不会干扰其他组件.
例子:
管理用户的组件可能使用前缀为的键,user:
管理日志的组件可能使用前缀为的键log:
.
在多租户系统中,我希望每个客户在Redis中使用单独的密钥空间,以确保他们的数据不会干扰.然后,前缀将类似于customer:<id>:
与特定客户相关的所有密钥.
使用Redis对我来说仍然是新的东西.我对这种分区模式的第一个想法是为每个分区使用单独的数据库标识符.但是,这似乎是一个坏主意,因为数据库的数量有限,似乎是一个即将被弃用的功能.
另一种方法是让每个组件获得一个IDatabase
实例,并RedisKey
使用它来为所有键添加前缀.(我正在使用StackExchange.Redis)
我一直在寻找一个IDatabase
自动为所有键添加前缀的包装器,以便组件可以按IDatabase
原样使用接口,而不必担心其键空间.我没找到任何东西.
所以我的问题是:在StackExchange Redis上使用分区键空间的推荐方法是什么?
我现在正在考虑实现我自己的IDatabase
包装器,它将为所有键添加前缀.我认为大多数方法只是将它们的调用转发给内部IDatabase
实例.但是,某些方法需要更多工作:例如SORT和RANDOMKEY.
c# ×4
.net ×2
.net-core ×1
asynchronous ×1
azure ×1
backup ×1
cors ×1
deadlock ×1
dynamic ×1
file-upload ×1
firefox ×1
hashcode ×1
html ×1
html5 ×1
http ×1
javascript ×1
jquery ×1
label ×1
memory-leaks ×1
netstat ×1
redis ×1
reflection ×1
string ×1
tcp ×1
web-worker ×1
windows ×1