我们正在与couchbase合作超过一年,并希望通过他们的.Net sdk改进我们的工作。
在他们的网站上,我找不到建议使用get / set的最佳方式。
我知道当我尝试使用时:CouchbaseClient.Get(key)
它可能会失败,
而且我们应该等待X时间再试一次。
我想了解在进行获取/设置过程时等待时间的最佳做法是什么。
任何遇到此问题的人都能告诉我这件事吗?
答案 0 :(得分:2)
我没有使用.net客户端,因为我只使用Java和Ruby与Couchbase,但高级概念将是相同的。
你说get操作可能会失败,你发现它失败很多吗?当智能客户端无法及时与群集通信或队列太满而无法接受新请求时,您必须处理多个异常,操作超时(非常罕见)。
你应该包装你的调用(获取/设置/添加)并捕获特定的异常,然后这一切都取决于系统的要求。如果您到达完整队列,多次重试请求将使情况变得更糟。如果没有异常,您可以在异常的情况下返回吗?
在我们的应用程序(REST API)中,如果我们捕获超时问题,那么我们抛出一个自定义异常,我们将返回给用户,通知他们将来重试。
如果我们有业务需求,我们必须重试,那么我们需要捕获超时并将请求放到队列或调用特定的重试策略。
如果您捕获任何一个异常,那么它可能表示您的系统正在或即将发生故障,因此请仔细监控。我认为Couchbase文档中的这个页面很好地涵盖了这些问题。
https://www.couchbase.com/docs/couchbase-devguide-2.0/about-client-timeouts.html
关于C#特定sdk http://www.couchbase.com/docs/couchbase-sdk-net-1.2/couchbase-sdk-net-configuration.html
的文档我希望这会有所帮助,如果没有随意扩展原始问题的更多细节。
答案 1 :(得分:2)
一般情况下,我建议你使用ExecuteXXX,其中XXX是一种操作方法,而不是常规/遗留的Get或Set方法。原因是这些方法返回有关操作的其他信息,此信息可用于定制重试策略。
有关详细信息,请阅读文档的这一部分:http://docs.couchbase.com/couchbase-sdk-net-1.3/#working-with-operation-results-and-error-codes
答案 2 :(得分:0)
感谢您的回答。
通过我在这个论坛中发现的那些答案和好帖子: Retry process
我写了一些代码,以下是其中一个方法的示例:
public static TResult Do<T,TResult>(Func<T,TResult> action, T param, TimeSpan retryInterval, int retryCount = 3)
{
for (int retry = 0; retry < retryCount; retry++)
{
try
{
return action(param);
}
catch (RetryOperationException)
{
Log.SaveFormat("Retry:{0} for action:{1}", "RetryProcessLog",retry, action.Method.Name);
Thread.Sleep(retryInterval);
}
catch (Exception ex)
{
Log.SaveFormat("Exception when retry:{0} error:{1}","RetryProcessLog",action.Method.Name,ex.Message);
return default(TResult);
}
}
return default(TResult);
}
public static T ExecuteGet<T>(string key)
{
var defaultReturnValue = default(T);
cacheHit("ExecuteGet", key);
var result = CacheClient.ExecuteGet<T>(CachePrefix + key);
if (result.Success)
{
return result.Value;
}
else if (result.StatusCode ==
CouchbaseStatusCode.StatusCodeExtension.ToInt(CouchbaseStatusCode.StatusCode.Busy)
||
result.StatusCode ==
CouchbaseStatusCode.StatusCodeExtension.ToInt(CouchbaseStatusCode.StatusCode.TemporaryFailure)
||
result.StatusCode ==
CouchbaseStatusCode.StatusCodeExtension.ToInt(CouchbaseStatusCode.StatusCode.SocketPoolTimeout)
||
result.StatusCode ==
CouchbaseStatusCode.StatusCodeExtension.ToInt(CouchbaseStatusCode.StatusCode.UnableToLocateNode)
||
result.StatusCode ==
CouchbaseStatusCode.StatusCodeExtension.ToInt(CouchbaseStatusCode.StatusCode.NodeShutdown)
||
result.StatusCode ==
CouchbaseStatusCode.StatusCodeExtension.ToInt(CouchbaseStatusCode.StatusCode.OperationTimeout))
{
Log.SaveFormat("Error:{0}:{2} in ExecuteGet for key:{1}. Going to throw RetryOperationException",
"CacheManager", result.StatusCode, key,result.Message);
throw new RetryOperationException();
}
Log.SaveFormat("Error:{0}:{2} in ExecuteGet for key:{1}", "CacheManager", result.StatusCode, key,result.Message);
return defaultReturnValue;
}
这只是一个示例,您可以添加更多方法重载,这些方法重载可以获得多个param或其他没有返回值的方法。 第二种方法在不同的类中,并使用ExecuteGet。
以下是一个使用示例:
var result = RetryProcess.Do(CacheManager.ExecuteGet<long>, keyOfValue, TimeSpan.FromMilliseconds(10));
希望它有所帮助。