行为模式-命令|策略|状态

https://refactoringguru.cn/design-patterns 设计模式

本质1:发送者(遥控器,食客),与接收者(电视机,厨师),通过命令对象进行沟通,命令作为一个对象在两者之间进行传递,命令封装了接收者(电视机,厨师)和一些动作;

本质2:命令模式的本质就是将命令对象进行封装打包,将发出命令的责任和执行命令的责任进行解耦,命令模式中发送者只需要知道如何发送请求命令,无须关心命令执行具体过程;

本质3:命令模式支持撤销、命令模式队列请求和日志请求


命令模式-示例1

厨师(单例模式),命令的实际执行者;  命令:做热菜、做凉菜、烧汤。。;  顾客:命令收集、下发、触发者

https://blog.youkuaiyun.com/zhi_fu/article/details/77691694

当需要先将一个函数登记上,然后再以后调用此函数时,就需要使用命令模式,其实这就是回调函数

//只有一个厨师,单例模式
public class ChuShi {
    public void cook(String m) {
        System.out.println(m);
    }
}
public interface Command {
    void execute();
}

public class LiangCaiCommand implements Command{
    private ChuShi chushi;
    public LiangCaiCommand(ChuShi chushi){
        this.chushi = chushi;
    }

    @Override
    public void execute() {
        this.chushi.cook("厨师拍黄瓜");
    }
}
public class ReCaiCommand implements Command{
    private ChuShi chushi;
    public ReCaiCommand(ChuShi chushi){
        this.chushi = chushi;
    }

    @Override
    public void execute() {
        this.chushi.cook("厨师炒土豆丝");
    }
}
//顾客,点菜+下单
public class Consumer {
    private List list = new ArrayList();
    public void orderDishes() {
        for (int i = 0; i < list.size(); i++) {
            Command command = (Command)list.get(i);
            command.execute();
        }
    }

    public void addCommand(Command command) {
        list.add(command);
    }

}
public class Client {
    public static void main(String[] argv) {
        //单例厨师来执行命令
        ChuShi chef=new ChuShi();
        //菜单
        Command commandLiang=new LiangCaiCommand(chef);
        Command commandRe=new ReCaiCommand(chef);

        //点菜
        Consumer cosumer=new Consumer();
        cosumer.addCommand(commandLiang);
        cosumer.addCommand(commandRe);
        //下单
        cosumer.orderDishes();

    }

}

命令模式-示例2https://www.cnblogs.com/chenssy/p/3202107.html

  • Command: 抽象命令类
  • ConcreteCommand: 具体命令类  :开机命令、关机命令、换台命令
  • Invoker: 调用者                             :遥控器
  • Receiver: 接收者                           :电视机
  • Client:客户类

优点:降低系统耦合、容易新增命令;缺点:系统有较多的命令类

使用场景:

  • 系统需要将请求调用者和请求接收者接口,使调用者和接受者不直接交互;
  • 系统需要在不同的时间指定请求、将请求排队和执行请求。
  • 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
  • 系统需要将一组操作组合在一起,即支持宏命令。

示例3 https://www.ibm.com/developerworks/cn/java/j-lo-serialNo/index.html

这里对上图做一个简单的解释,命令模式涉及到五个角色,分别为:

客户(Client)角色:创建一个具体命令(ConcreteCommand)对象,并设置命令的接收者。

命令(Command)角色:定义一个给所有命令类的抽象接口,定义了统一的 execute() 接口方法。

具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现 Command 接口,并实现 execute() 方法,负责调用接收者的相应操作。

请求者(Invoker)角色:负责调用由 Client 下达的对象执行请求。

接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法为行动方法。

https://blog.youkuaiyun.com/zdsicecoco/article/details/51332440


策略模式:https://www.runoob.com/design-pattern/strategy-pattern.html

  • 命令模式和策略模式的类图确实很相似,只是命令模式多了一个接收者(Receiver)角色;
  • 策略模式的意图是封装算法,它认为“算法”已经是一个完整的、不可拆分的原子业务
  • 命令模式则是对动作的解耦,把一个动作的执行分为执行对象(接收者角色)、执行行为(命令角色),让两者相互独立而不相互影响
  • 环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据,在上一个例子中相当于Staff。
  • 抽象策略类(Strategy):定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法,在上一个例子中相当于GrantReward。
  • 具体策略类(ConcreteStrategy):以Strategy接口实现某具体算法,在上一个例子中相当于GrantSuger,GrantMoonCake,GrantNone。

压缩、解压 https://www.kancloud.cn/sstd521/design/193630


状态模式:https://www.runoob.com/design-pattern/state-pattern.html

  • 状态模式和命令模式一样,也可以用于消除 if...else 等条件选择语句
  • 状态模式和策略模式是亲兄弟,两者非常相似
  • 策略模式封装的是不同的算法,算法之间没有交互,以达到算法可以自由切换的目的;而状态模式封装的是不同的状态,以达到状态切换行为随之发生改变的目的

 

 

 

 

 

<think>好的,我现在需要帮助用户理解Canary权重模式中删除主Ingress是否会导致错误,以及在合并配置时是否会导致请求中断。用户提到,当删除主Ingress:v1后,只剩下Canary Ingress:v2,这时候是否会有问题,同时合并配置到主Ingress:v2时删除Canary注释是否会中断请求。 首先,我需要回顾之前提供的分步骤解析,特别是关于配置迁移的部分。之前的回答指出,在权重达到100%后,必须将Canary配置合并到主Ingress并移除标记。但用户现在担心删除主Ingress会导致错误,因为剩下的Canary Ingress仍然是带有canary标记的版本,可能会影响后续更新。 首先,要澄清Canary Ingress的工作原理。Canary Ingress通常作为主Ingress的补充,用于分流部分流量。当权重达到100%时,所有流量都转向Canary,此时主Ingress实际上已经没有流量了。删除主Ingress:v1是否正确?根据Kubernetes Ingress控制器的实现,特别是Nginx Ingress,当主Ingress存在时,Canary Ingress的规则会与之合并,但一旦主Ingress被删除,Canary Ingress是否还能正常工作? 可能存在的问题是,如果主Ingress被删除,只剩下Canary Ingress,但Canary Ingress仍然带有canary标记,这时候是否会影响流量的处理?例如,某些Ingress控制器可能需要主Ingress的存在才能正确处理Canary规则。如果主Ingress被删除,可能会导致配置错误,因为Canary Ingress可能依赖于主Ingress的存在。 接下来,用户在合并配置到新的主Ingress:v2时,删除Canary注释是否会导致请求中断。这个问题涉及到Kubernetes的配置更新机制。当修改Ingress资源时,Ingress控制器通常会重新加载配置,可能会引起短暂的流量中断,但需要确认具体控制器的行为。 另外,用户可能误解了流程中的步骤,即删除主Ingress:v1和创建新的主Ingress:v2的顺序是否正确。正确的流程应该是先创建新的主Ingress:v2(基于Canary Ingress的配置,但移除canary标记),然后再删除旧的Canary Ingress和主Ingress:v1,以确保流量的无缝切换。 因此,之前的流程可能存在错误,正确的步骤应该是: 1. 将Canary Ingress:v2的配置复制到新的主Ingress:v2,并移除canary标记。 2. 应用新的主Ingress:v2,此时流量应该仍然由Canary Ingress:v2处理,因为其权重是100%。 3. 验证新的主Ingress:v2配置正确后,删除Canary Ingress:v2和旧的主Ingress:v1。 这样,在删除旧资源之前,新的主Ingress已经存在,避免了出现没有主Ingress的情况。同时,删除Canary Ingress时,流量会自动切换到新的主Ingress,因为此时Canary权重已经转移到主Ingress。 关于删除canary注释是否导致中断,需要确认在更新Ingress时,控制器是否会平滑地重新加载配置。通常,Ingress控制器如Nginx会通过热重载来避免中断,但可能会有短暂的影响,尤其是在大规模部署中。因此,建议在低流量时段执行此类操作,并确保控制器配置了正确的重载策略。 总结用户的问题:删除主Ingress可能会导致问题,正确的做法是先创建新的主Ingress,再删除旧的。而合并配置时删除canary注释通常不会导致中断,但需注意控制器的行为。</think>--- ### Canary 权重模式的核心操作详解 --- #### 一、操作时序错位的风险与修正方案 ##### 原始流程的潜在问题 ```mermaid graph TD A[主Ingress:v1] -->|删除操作在前| B[仅剩Canary Ingress:v2] B -->|无主Ingress存在| C[控制器可能拒绝配置] C -->|新版本发布| D[无法创建新的Canary] ``` ##### 修正后的安全流程 ```mermaid graph LR A[主Ingress:v1] -->|第一步| B[创建新主Ingress:v2] B -->|第二步| C[删除Canary标记] C -->|第三步| D[删除旧主Ingress:v1] D -->|第四步| E[清理Canary Ingress] ``` --- #### 二、关键操作的技术实现细节 ##### 1. 配置迁移的正确方式 **错误操作示例**:直接删除旧主Ingress ```bash kubectl delete ingress main-v1 # 危险操作!此时可能丢失路由规则 ``` **正确操作步骤**: 1. **创建无Canary标记的新主Ingress** ```yaml # main-v2.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: main-v2 annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: app-v2 port: number: 80 ``` 2. **验证双Ingress并存时的流量分布** ```bash # 观察流量是否100%流向v2 kubectl exec -it ingress-nginx-controller -- \ curl http://localhost:10246/configuration/backends ``` 3. **分阶段删除旧资源** ```bash kubectl delete ingress main-v1 --wait=true # 等待配置同步完成 kubectl delete ingress canary-v2 ``` ##### 2. 注解移除的平滑过渡 **中断风险场景**:直接编辑Canary Ingress ```bash kubectl annotate ingress canary-v2 \ # 错误!会触发配置重载 nginx.ingress.kubernetes.io/canary- ``` **零中断方案**: 1. 创建新主Ingress时**完全复制配置** 2. 保持Canary Ingress的100%权重不变 3. 通过**服务选择器切换**完成最终迁移 ```yaml # service.yaml (最终状态) spec: selector: app: myapp version: v2 # 确保与Pod标签匹配 ``` --- #### 三、实际生产环境验证指标 在迁移过程中需监控以下关键指标: | 监控维度 | 健康阈值 | 检测命令示例 | |------------------|------------------------------|----------------------------------------| | 配置生效时间 | < 5秒 | `kubectl get ingress -w` | | 502错误率 | < 0.1% | `kubectl logs -l app=nginx-ingress | grep 502` | | 长连接中断数 | 增长量 < 10% | `netstat -an | grep ESTABLISHED | wc -l` | | 客户端超时率 | 99分位 < 2000ms | Prometheus直方图监控 | --- #### 四、典型错误场景模拟与修复 **案例现象**: 开发者在删除旧主Ingress后直接修改Canary Ingress的注解,导致出现以下异常: ``` Warning ConfigError 2s (x3 over 4s) nginx-ingress-controller Error validating ingress rule: no upstream defined for host example.com ``` **根本原因分析**: Nginx Ingress控制器的配置生成机制需要至少一个**非Canary**的基准Ingress存在。当所有Ingress都带有Canary标记时,控制器无法生成有效配置。 **修复步骤**: 1. 立即恢复旧主Ingress的备份 ```bash kubectl apply -f main-v1.bak.yaml ``` 2. 创建符合规范的新主Ingress 3. 执行金丝雀流量切换流程 4. 使用`kubectl rollout undo`回滚错误变更 --- #### 五、高级实践:声明式版本切换 通过GitOps实现自动化版本管理: ```yaml # app-of-apps.yaml apiVersion: argoproj.io/v1alpha1 kind: Application spec: source: repoURL: git@github.com:myorg/ingress-config.git targetRevision: HEAD path: overlays/prod syncPolicy: automated: prune: true selfHeal: true syncOptions: - CreateNamespace=true ``` **版本切换工作流**: 1. 在Git仓库中创建新分支`release/v2` 2. 修改`kustomization.yaml`指向新Ingress配置 3. Argo CD自动同步配置到集群 4. 通过预置的验收测试后合并到main分支 --- 通过这种严谨的操作流程设计,完全规避了"无主Ingress"的异常状态,同时确保了流量切换的平滑性。核心原则是:**永远保持至少一个非Canary的主Ingress在线,通过先创建后删除的顺序保证配置连续性**。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值