什么是程序设计里的 backoff pattern

Posted JerryWangSAP

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是程序设计里的 backoff pattern相关的知识,希望对你有一定的参考价值。

Backoff pattern 是一种程序设计模式,通常用于处理因高负载或故障而导致的请求失败或错误。该模式基于一种简单的策略,即当请求失败时,等待一段时间后重试,等待时间逐渐增加,直到成功或达到最大重试次数为止。

在实际应用中,Backoff pattern 通常会包含以下几个要素:

初始等待时间:在第一次重试之前等待的时间,通常是一个较短的固定时间。

等待时间递增因子:每次重试时等待时间的增加因子,通常是一个固定的倍数或增量。

最大等待时间:达到该等待时间后不再进行重试,防止过度等待或死循环。

最大重试次数:达到该重试次数后停止重试,防止无限重试或死循环。

Backoff pattern 的优点是能够在高负载或故障情况下有效地处理请求失败,并减轻服务器负载。然而,该模式也存在一些缺点,例如可能会导致响应时间变慢,因为每次失败都需要等待一段时间后才会重试,并且需要在客户端上实现复杂的逻辑来处理重试。

一个简单的实现 Backoff pattern 的例子可以是以下的伪代码:

def make_request():
    retries = 0
    while retries < MAX_RETRIES:
        try:
            response = send_request()
            return response
        except Exception as e:
            if retries == MAX_RETRIES - 1:
                raise e
            retries += 1
            wait_time = INITIAL_WAIT_TIME * (BACKOFF_FACTOR ** retries)
            wait_time = min(wait_time, MAX_WAIT_TIME)
            time.sleep(wait_time)

Spartacus 里的 backoff 机制的一个例子:

下面是一个使用 Angular HttpClient 实现 backoff pattern 的 TypeScript 代码示例:

import  Injectable  from \'@angular/core\';
import  HttpClient  from \'@angular/common/http\';
import  Observable, throwError  from \'rxjs\';
import  retryWhen, delay, take, mergeMap  from \'rxjs/operators\';

@Injectable(
  providedIn: \'root\'
)
export class DataService 

  constructor(private http: HttpClient)  

  getData(url: string): Observable<any> 
    return this.http.get(url).pipe(
      retryWhen(errors => errors.pipe(
        // 每秒重试一次,最多重试 3 次
        delay(1000),
        take(3),
        // 如果是 500 错误,则进行重试
        mergeMap(response => 
          if (response.status === 500) 
            return throwError(response);
          
          return response;
        )
      ))
    );
  


在这个示例中,我们定义了一个名为 DataService 的服务,该服务使用 Angular HttpClient 来获取数据。我们使用 retryWhen 操作符来实现 backoff pattern,它将在发生错误时重试 HTTP 请求。

在 retryWhen 中,我们使用 delay 操作符来指定每次重试之间的延迟时间,这里设置为 1000 毫秒。我们还使用 take 操作符来指定最大重试次数,这里设置为 3 次。

在 mergeMap 操作符中,我们检查响应的状态码是否为 500。如果是,我们使用 throwError 操作符将错误抛出,触发 retryWhen 中的重试逻辑。如果响应状态码不是 500,则直接返回响应。

因此,这个示例中的 backoff pattern 实现了在 HTTP 请求失败时进行重试,最多重试 3 次,每次重试之间延迟 1 秒。

菜鸟理解的工厂模式(Factory Pattern)是什么样子的?

直接开始说了,不浪费园友宝贵的时间!

什么是工厂模式?

 

  在学习前,先问一下:“它是什么?”。

  工厂模式,它是项目里面常用的设计模式之一。

  它是属于创建型模式,简单的理解创建型模式就是将实例化工作交给另外一个对象来完成。

  工厂模式(又称静态工厂模式 Static Factory Method),它算是软件设计模式中最简单的模式了。  

为了解决什么问题?

 

  工厂模式使代码清晰,降低耦合度,调用者通过 接口/抽象类来获得想要的实例化,而无需关心细节上是如何实现的。

  工厂模式是一种典型的解耦模式,迪米特法则在工厂模式中表现的尤为明显。

  (说的比较简单,看了多个网站与博客,我个人认为这句话是工厂模式要解决的最根本的问题,如果有兴趣,可以去看一下其它文章。)

 

什么时候使用?

 

  工厂模式属于创建类模式,在同的条件下创建不同的对象实例时,可以使用工厂方法模式。

  简单的对象,特别是只需要通过new就可以完成创建的对象,无需使用工厂模式。(就是复杂的时候才用工厂,简单不需要用,反而增加程序的复杂度。)

 

实践加深理解:

 

  我请大家去饭店吃饭,有东北菜(我是东北yin),浙江菜,北京菜等等等等,我把你们带进饭店,然后点了东北菜。这个过程,其实就是工厂模式的一种实现。

  首先,不管它是什么菜系的饭店,首先它必须是个“饭店”,必须会做菜(简单描述一下),以下是代码实践过程。

  

  一、我们创建一个饭店的接口类,里面只有一个动作,用来规定所有饭店都必须会做菜!!!

    /// <summary>
    /// 饭店接口类
    /// </summary>
    public interface IRestaurants
    {

        /// <summary>
        ///  每个饭店必须会做饭
        /// </summary>
        /// <returns></returns>
        string Cook();
    }
View Code

  二、接下来创建几个菜系的具体饭店。

    /// <summary>
    /// 北京饭店
    /// </summary>
    class Beijing : IRestaurants
    {
        public string Cook()
        {
            return "给你北京菜";
        }
    }
View Code
    /// <summary>
    /// 东北饭店
    /// </summary>
    class Dongbei : IRestaurants
    {
        public string Cook()
        {
            return "给你东北菜";
        }
    }
View Code
    /// <summary>
    /// 浙江饭店
    /// </summary>
    class Zhejiang : IRestaurants
    {
        public string Cook()
        {
            return "给你浙江菜";
        }
    }
View Code

  三、菜馆有了,接下来这个就是简单工厂模式里的重点了。如何让这些饭店能够正确的给我上菜呢?(如果读者说去东北饭店肯定不能给上北京菜,那请您出门右拐,跪哭!!!)

    这时就需要有个“工厂”来协助我要告诉什么饭店做菜了(创建哪个饭店的实例)。

    /// <summary>
    /// 饭店工厂类,根据名字创建饭店的实例。
    /// </summary>
    public class RestaurantSimpleFactory
    {
        public IRestaurants GiveMe(string name)
        {
            switch (name)
            {
                case "Dongbei":
                    return new Dongbei();
                case "Beijing":
                    return new Beijing();
                case "Zhejiang":
                    return new Zhejiang();
                default:
                    return new Dongbei();
            }
        }
    }
View Code

  四、准备工作完毕,可以上菜了。

    public class Program
    {
        static void Main(string[] args)
        {
            //创建饭店工厂实例
            var restaurantSimpleFactory = new RestaurantSimpleFactory();
            //使用饭店接口招收实现它的饭店实例
            IRestaurants restaurant = restaurantSimpleFactory.GiveMe("Dongbei");
            string cookWhat = restaurant.Cook();
            Console.WriteLine("饭店:" + cookWhat);
            Console.ReadLine();
        }
    }
View Code

 


 

图解:这是根据我个人的理解画的导图,可能与网络上大牛们的不太一样。

 

 


Tag:简单工厂中还包含了另一种实现,“工厂方法”,接下来深入学习一下。

如果我的理解有误,想喷就喷没关系,别骂我就好!可能在您的愤怒中会学习到我没有理解的。谢谢观看!

以上是关于什么是程序设计里的 backoff pattern的主要内容,如果未能解决你的问题,请参考以下文章