简体   繁体   English

使用CouchbaseClient的最佳实践

[英]Best practice for working with CouchbaseClient

We are working with couchbase for more than a year and want to improve our work with their .Net sdk. 我们正在使用Couchbase超过一年,并希望通过他们的.Net SDK来改进我们的工作。

In their website i could not find the recommendation for the best way to use get/set. 在他们的网站上,我找不到使用get / set的最佳方法的推荐。

I know that when i am trying to use : CouchbaseClient.Get(key) it can fail, and than we should wait for X time and try again. 我知道当我尝试使用: CouchbaseClient.Get(key)时可能会失败,然后我们应该等待X时间再试一次。

I want to understand what is the best practice for the waiting times when doing a get/set process. 我想了解在进行获取/设置过程时等待时间的最佳做法是什么。

Can anyone who encounter this issue advise me about it please? 遇到此问题的任何人都可以向我提出建议吗?

I haven't used the .net client as I only work with Java and Ruby with Couchbase but the high level concepts are going to be the same. 我没有使用.net客户端,因为我只使用Java和Ruby和Couchbase,但是高级概念将是相同的。

You say that the get operation can fail, do you find it fails a lot? 您说get操作可能失败,您发现它失败很多吗? You have to handle several exceptions, operation timeout when the smart client fails to communicate in a timely manner with the cluster or the queue is too full to accept new requests (meant to be very rare). 您必须处理一些异常,当智能客户端无法及时与集群通信或队列太满而无法接受新请求时(操作很少),操作超时。

You should wrap your calls (get/set/add) and catch the particular exception and then it all depends on what the requirements of your system are. 您应该包装调用(获取/设置/添加)并捕获特定的异常,然后这完全取决于系统的要求。 If you are reaching a full queue retrying requests multiple times is going to make the situation worse. 如果您到达一个完整的队列,则多次重试请求将使情况变得更糟。 Is there not a default you can return in the case of an exception? 如果发生异常,可以返回默认值吗?

In our application (REST API) if we catch a timeout issue then we throw a custom exception which we return to the user notifying them to retry in the future. 在我们的应用程序(REST API)中,如果遇到超时问题,则会抛出一个自定义异常,该异常将返回给用户,通知他们将来重试。

IF we had the business requirement that we had to retry then we'd need to catch the timeout and either place the request onto a queue or invoke a specific retry strategy. 如果我们有必须重试的业务要求,那么我们需要捕获超时并将请求放入队列或调用特定的重试策略。

If you are catching either exception then it could be a sign that your system is or is about to go down, so monitor it carefully. 如果您捕获到任何一个异常,则可能表明您的系统即将或即将宕机,因此请仔细监视它。 I think this page from the Couchbase documentation covers the issues quite well. 我认为Couchbase文档中的此页面很好地涵盖了这些问题。

https://www.couchbase.com/docs/couchbase-devguide-2.0/about-client-timeouts.html https://www.couchbase.com/docs/couchbase-devguide-2.0/about-client-timeouts.html

And documentation on the C# specific sdk http://www.couchbase.com/docs/couchbase-sdk-net-1.2/couchbase-sdk-net-configuration.html 以及有关C#特定sdk的文档http://www.couchbase.com/docs/couchbase-sdk-net-1.2/couchbase-sdk-net-configuration.html

I hope this helps, if not feel free to expand on your original question with more details. 我希望这会有所帮助,即使不是您可以随意在原始问题上提供更多详细信息,也可以。

In general, I suggest you use the ExecuteXXX where XXX is an operation methods as opposed to the regular/legacy Get or Set methods. 通常,我建议您使用ExecuteXXX,其中XXX是操作方法,而不是常规/旧式Get或Set方法。 The reason is that these methods return additional information about the operation and this info can be used to tailor your retry strategy. 原因是这些方法返回有关该操作的其他信息,并且此信息可用于定制重试策略。

For more information, read this portion of the documentation: http://docs.couchbase.com/couchbase-sdk-net-1.3/#working-with-operation-results-and-error-codes 有关更多信息,请阅读文档的此部分: http : //docs.couchbase.com/couchbase-sdk-net-1.3/#working-with-operation-results-and-error-codes

Thanks for the answers here. 感谢您在这里的答案。

By those answers and good post i found in this forum: Retry process 通过这些答案和我在本论坛中找到的好帖子: 重试过程

I wrote some code and here is an example for one of its methods: 我写了一些代码,这是其中一种方法的示例:

            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;
        }

This is just an example and you can add more method overloads that gets more than one param or other method without a return value. 这只是一个示例,您可以添加更多的方法重载,这些重载获得多个参数或其他方法而没有返回值。 The second method is in different class and uses the ExecuteGet. 第二种方法在不同的类中,并使用ExecuteGet。

And here is an example of usage: 这是用法示例:

var result = RetryProcess.Do(CacheManager.ExecuteGet<long>, keyOfValue, TimeSpan.FromMilliseconds(10));

Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM