08-05 应用层设计

news2024/11/29 3:57:09

伸缩性的架构设计——服务器集群的伸缩性

DNS负载均衡

DNS服务器将访问的域名转发到对应的网关,网关层做反向代理。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

利用消息组件对业务场景进行解耦

适合用消息组件解耦的场景

  • 长任务(时间长,逻辑复杂,可异步)
  • 非实时(轻任务、时效性要求不高、可异步化)
  • 发布订阅(多下游相同语义)

长任务

  • 商户数据变更——触发风控的自动评分(耗时的长任务)
  • 商品中心——商品编辑&发布(复杂的业务场景)
  • 报表系统——生成报表并发送

非实时

  • 用户验证——手机验证码
  • 通知消息——验证邮箱、用户通知
  • 支付业务——付款回调接口

发布订阅

在这里插入图片描述
在这里插入图片描述

性能规划——性能指标和应用层优化策略

性能测试指标

  • RT响应时间
  • QPS每秒访问(吞吐量)
  • 并发数(并发能力)

复杂业务性能优化

在这里插入图片描述

构建性能基线

在这里插入图片描述

稳定性测试

经过一段时间使用后,发现一些潜在的Bug

缓存使用模式

既然使用缓存,那就肯定会存在缓存数据和DB数据不一致的问题,只是不一致时间长短的问题

全量缓存场景

在这里插入图片描述

时效性缓存场景

在这里插入图片描述

在这里插入图片描述

业务设计原则——有限状态机的流转

在这里插入图片描述
在这里插入图片描述

基于Spring Statemachine的轻量级状态机

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.learn</groupId>
    <artifactId>statemachine</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-parent</artifactId>
        <version>2.2.1.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.statemachine</groupId>
            <artifactId>spring-statemachine-core</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

biz

package com.learn.architect.biz;

/**
 * @author YSK
 * @since 2023/5/15 14:14
 */
public enum OrderEvent {
    PLACE_ORDER,//下单
    PAID,//付款完成
    DELIVERED//开始运输
}
package com.learn.architect.biz;

/**
 * @author YSK
 * @since 2023/5/15 14:13
 */
public enum OrderState {
    CREATED,
    PENDING_PAYMENT,
    PENDING_DELIVERY,
    ORDER_COMPLETE
}

config

package com.learn.architect.config;

import com.learn.architect.biz.OrderEvent;
import com.learn.architect.biz.OrderState;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;

import java.util.EnumSet;

/**
 * @author YSK
 * @since 2023/5/15 14:31
 */
@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderState, OrderEvent> {
    @Override
    public void configure(StateMachineStateConfigurer<OrderState,OrderEvent> states) throws Exception{
        //声明状态和其他状态
        states.withStates()
                .initial(OrderState.CREATED)
                .states(EnumSet.allOf(OrderState.class));

    }

    /**
     * 配置状态机如何做流转
     */
    @Override
    public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {
        transitions
                .withExternal()
                    .source(OrderState.CREATED)
                    .target(OrderState.PENDING_PAYMENT)
                    .event(OrderEvent.PLACE_ORDER)
                .and().withExternal()
                    .source(OrderState.PENDING_PAYMENT)
                    .target(OrderState.PENDING_DELIVERY)
                    .event(OrderEvent.PAID)
                .and().withExternal()
                    .source(OrderState.PENDING_DELIVERY)
                    .target(OrderState.ORDER_COMPLETE)
                    .event(OrderEvent.DELIVERED);
    }
}

listener

package com.learn.architect.listener;

import com.learn.architect.biz.OrderState;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.Message;
import org.springframework.statemachine.annotation.OnTransition;
import org.springframework.statemachine.annotation.WithStateMachine;

/**
 * @author YSK
 * @since 2023/5/15 14:17
 */
@WithStateMachine
@Slf4j
@Data
public class OrderListener {
    private String orderState = OrderState.CREATED.name();

    @OnTransition(target = "PENDING_PAYMENT")
    public void pendingPayment(Message message) {
        log.info("订单创建,等待付款,states={},header={}",
                OrderState.PENDING_PAYMENT.name(),
                message.getHeaders().get("orderId"));
        //todo 业务流程
        setOrderState(OrderState.PENDING_PAYMENT.name());

    }

    @OnTransition(target = "PENDING_DELIVERY")
    public void pendingDelivery(Message message) {
        log.info("订单已付款,等待发货,states={}",
                OrderState.PENDING_DELIVERY.name(),
                message.getHeaders().get("orderId"));
        //todo 业务流程
        setOrderState(OrderState.PENDING_DELIVERY.name());

    }

    @OnTransition(target = "ORDER_COMPLETE")
    public void complete(Message message) {
        log.info("订单完成,states={}",
                OrderState.ORDER_COMPLETE.name(),
                message.getHeaders().get("orderId"));
        //todo 业务流程
        setOrderState(OrderState.ORDER_COMPLETE.name());

    }
}

run

package com.learn.architect;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

/**
 * @author YSK
 * @since 2023/5/15 14:54
 */
@SpringBootApplication
public class ApplicationStater {

    @Bean
    public MyRunner myRunner() {
        return new MyRunner();
    }

    public static void main(String[] args) {
        SpringApplication.run(ApplicationStater.class,args);
    }
}
package com.learn.architect;

import com.learn.architect.biz.OrderEvent;
import com.learn.architect.biz.OrderState;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.Ordered;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;

import javax.annotation.Resource;

/**
 * @author YSK
 * @since 2023/5/15 14:46
 */
public class MyRunner implements CommandLineRunner {
    @Resource
    StateMachine<OrderState,OrderEvent> stateMachine;
    @Override
    public void run(String... args) throws Exception {
        stateMachine.start();
        Message<OrderEvent> message = MessageBuilder
                .withPayload(OrderEvent.PLACE_ORDER)
                .setHeader("orderId", "998")
                .build();
        stateMachine.sendEvent(message);
        stateMachine.sendEvent(OrderEvent.PAID);
        stateMachine.sendEvent(OrderEvent.DELIVERED);
    }
}

test

package com.learn.architect;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @author YSK
 * @since 2023/5/15 14:57
 */
@SpringBootTest
public class StateMachineTest {

    @Test
    public void run() {

    }
}

在这里插入图片描述

面试题

业务性能调优

  • 首先考虑异步化(MQ、异步编排、池化等)
  • 分布式、本地缓存
  • 数据异构(非一致性场景快速返回、查找)

缓存的一致性问题

  • 读写场景的一致性
  • Setnx,watch+multi乐观锁

复杂业务中状态的流转(订单系统中的设计)

  • 规则引擎
  • 轻量级状态机实现Spring Statemachine

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/528380.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React Antv G2Plot 「指标拆解图」 前端可视化实战 实现渲染、重置、筛选功能

背景 实现对指定数据的「指标拆解图」 渲染&#xff0c;并且可以根据筛选项进行变化。 任务分解 antv 的图表&#xff0c;以及请求后端的载荷对传入的数据结构有严格要求 一个工具函数将后端接口返回的数据格式化成 antv 图表要求的格式一个工具函数将前端提交的请求数据格…

Copilot入门

文章目录 简介安装初试快捷键取消订阅参考文献 简介 Copilot 是一款 GitHub 和 OpenAI 合作开发的 AI 结对编程工具&#xff0c;支持 Visual Studio、Neovim、VS Code、JetBrains IDEs&#xff0c;用于自动补全代码。 本文以 Python PyCharm 为例。 安装 GitHub Copilot&am…

【数据结构】栈及其实现

目录 &#x1f920;前言 什么是栈&#xff1f; 栈的定义及初始化 栈的定义 栈的初始化 栈的判空 栈顶压栈 栈顶出栈 栈的数据个数 栈的销毁 完整代码 总结 &#x1f920;前言 学了相当长一段时间的链表&#xff0c;总算是跨过了一个阶段。从今天开始我们将进入栈和…

什么是AIGC

AIGC是人工智能创意生成的缩写&#xff08;Artificial Intelligence Generated Creativity&#xff09;&#xff0c;指的是利用人工智能技术实现的创意生成。通俗来说&#xff0c;就是让机器产生新颖、独特且有创造性的作品或方案&#xff0c;例如音乐、绘画、视频、文本等等。…

Sui基金会宣布面向APAC的Office Hours计划

诚挚邀请构建者与Sui基金会的Growth团队一起开启“Office Hours”计划&#xff0c;共同努力&#xff0c;迈向业务增长的下一步。 Sui基金会致力于推动Sui在全球范围内的普及。为此&#xff0c;我们通过积极支持开发人员的开发者资助计划、Builder House和大使计划在Sui上开始…

如何高效运行Omniverse,无惧本地硬件压力

无论是创造能够表达原始情感的逼真数字人&#xff0c;还是构建身临其境的虚拟世界&#xff0c;全球设计、工程、创意和其他行业的人士都在通过3D工作流&#xff0c;突破技术壁垒并拓展创意可能&#xff0c;让虚拟世界和现实世界交融与观众产生共鸣。 而在众多连接未来创作内容的…

ES6中函数新增的方式方法

1.1函数形参的默认值 1.1.1基本用法 ES6 之前&#xff0c;不能直接为函数的参数指定默认值&#xff0c;只能采用变通的方法。如下代码&#xff1a; function func(x,y){y y || "tom";console.log(x,y);}func("hello"); //hello tomfunc("…

数据库标准化之核心结局变量集(COS)

COS介绍 核心结果集&#xff08;COS&#xff09;是在特定健康状况下进行的所有临床试验中应测量和报告的一组最少结局变量集。COS数据库是这些变量集的集合&#xff0c;这些集合是通过循证和迭代过程开发的。该数据库由COMET倡议维护&#xff0c;该计划是研究人员&#xff0c;…

Linux 系统上 C 程序的编译与调试 2 总结

1.gcc分布编译链接 &#xff08;1) 预编译 : gcc -E main.c -o main.i (2) 编译&#xff1a; gcc -S main.i -o main.s (3) 汇编&#xff1a; gcc -c main.s -o main.o (4) 链接&#xff1a; gcc main.o -o main gcc -E hello.c -o hello.i #预处理 gcc -S hello.i -o h…

【FMC134】ADC12DJ3200之4通道3.2GSPS(2 通道6.4GSPS) 12 位AD高速采集子卡设计原理图及调试经验

板卡概述 FMC134 是一款4 通道3.2GSPS&#xff08;或者配置成2 通道6.4GSPS&#xff09;采样率的12 位AD 采集FMC子卡模块&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.4 规范&#xff0c;可以作为一个理想的IO 模块耦合至FPGA 前端&#xff0c;射频模拟信号数字化后通过…

【多线程进阶一】常见的锁策略

目录 一、常见的锁策略 &#x1f345;1、常见的锁策略 &#x1f345;2、Synchronized实现了哪些锁策略&#xff1f; &#x1f345;3、自旋锁的实现方式—CAS &#xff08;1&#xff09;CAS伪代码 &#xff08;2&#xff09;演示 使用CAS方式来实现自增操作&#xff1a; &am…

Linux 系统修改环境变量的方法

1. Linux 系统修改环境变量 正常情况下改变环境变量可以修改的文件有两类&#xff1a; 第一类是 “系统的全局环境变量”&#xff0c;修改之后可作用于整个系统包含的所有用户都会生效&#xff1b;(文件&#xff1a;/etc/profile) 第二类是 “局部环境变量”&#xff0c;也就…

Linux C程序多文件编译

C程序多文件编译 在Linux平台C编程&#xff0c;实现求两数最大值和两数之和的功能 1.编写add.c wysDESKTOP-2OU3HRV:~/mycode/day02$ vi add.c1 int add(int x,int y)2 {3 return x y;4 } 2.编写头文件add.h wysDESKTOP-2OU3HRV:~/mycode/day02$ vi add.hint add(…

Python 实验五 字符串与正则表达式

1.输入一个字符串&#xff0c;将该字符串中下标为偶数的字符组成新串并通过字符串格式化方式显示。 a input("请输入一个字符串&#xff1a;") b a[1::2] print("老串为&#xff1a;%a&#xff0c;新串为&#xff1a;%a"%(a,b))2.编写程序&#xff0c;生…

LInux系统下使用git的三板斧以及报错处理

LInux使用git 我们应该知道git是什么东西&#xff0c;还有git的三板斧&#xff0c;git是一个工具&#xff0c;使用git来将文件上传到代码仓库 文章目录 LInux使用gitcloneaddcommitpush查看当前git的状态 clone 第一步找到你创建的仓库&#xff0c;然后复制http地址&#xf…

目前可以用的ChatGPT网址大全

ChatGPT是一个基于人工智能的聊天机器人&#xff0c;可以与用户进行自然语言交互。它可以回答各种问题&#xff0c;提供有用的信息和建议&#xff0c;还可以进行闲聊和娱乐。ChatGPT使用最先进的自然语言处理技术&#xff0c;可以理解和解释人类语言&#xff0c;从而提供准确和…

【Linux】IO多路转接 - epoll

文章目录 I/O多路转接之epollepoll初识epoll的相关系统调用函数epoll_createepoll_ctlepoll_wait epoll工作原理epoll服务器-*epoll的优缺点epoll工作方式对比LT和ET I/O多路转接之epoll epoll初识 epoll也是系统提供的一个多路转接的接口,epoll才是使用和面试的重点,在效率和…

SpringBoot【开发实用篇】---- 整合第三方技术(缓存)

SpringBoot【开发实用篇】---- 整合第三方技术&#xff08;缓存&#xff09; SpringBoot内置缓存解决方案手机验证码案例SpringBoot整合Ehcache缓存SpringBoot整合Redis缓存SpringBoot整合Memcached缓存SpringBoot整合jetcache缓存纯远程方案纯本地方案本地远程方案远程方案的数…

tomcat控制台打印乱码解决

一、注册表修改 HKEY_CURRENT_USER ->console ->tomcate 新增 32位 CodePage 16进制 fde9 二、idea 中配置 Tomcat 后启动服务&#xff0c;输出打印日志乱码问题 解决办法&#xff1a; ①、打开安装idea文件路径&#xff0c;在bin目录下&#xff0c;找到下面两个文件 ②…

图像动态裁剪

1. 背景 以两级级联模型为例&#xff0c;第一级目标检测模型用于检测人员&#xff0c;第二级目标检测模型用于检测手机、对讲机等。然后实际数据采集过程中&#xff0c;手机、对讲机这些设备并不在人员的一级检测框内&#xff0c;使得二级模型训练的样本较少。 二级目标检测模…