程序员高频率面试题-整理篇
Redis 除了做缓存,还能做什么?
分布式锁:通过 Redis 来做分布式锁是一种比较常见的方式。通常情况下,我们都是基于 Redisson 来实现分布式锁。
限流:一般是通过 Redis + Lua 脚本的方式来实现限流。
消息队列:Redis 自带的 List 数据结构可以作为一个简单的队列使用。Redis 5.0 中增加的 Stream 类型的数据结构更加适合用来做消息队列。它比较类似于 Kafka,有主题和消费组的概念,支持消息持久化以及 ACK 机制。
延时队列:Redisson 内置了延时队列(基于 Sorted Set 实现的)。
分布式 Session :利用 String 或者 Hash 数据类型保存 Session 数据,所有的服务器都可以访问。
复杂业务场景:通过 Redis 以及 Redis 扩展(比如 Redisson)提供的数据结构,我们可以很方便地完成很多复杂的业务场景比如通过 Bitmap 统计活跃用户、通过 Sorted Set 维护排行榜。
如何保证redis和mysql数据一致
- 先删缓存再更新数据库/先更新数据库再删缓存。
- 先更新Redis,再更新MySQL。
- 只更新缓存,由缓存自己异步更新数据库。
SpirngCloud的五大核心组件
Eureka:服务注册中心
Ribbon:客户端负载均衡
Hystrix:熔断器,实现断路器模式,帮助服务依赖中出现的延迟和故障提供容错机制
Fegin:声明式的Http客户端
Zuul:服务网关
Archaius:外部化配置参数组件
alibaba集成的spring cloud组件有哪些?
1、Alibaba Nacos:Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。换句话说Nacos就是注册中心和配置中心的组合。等价于:Nacos=Eureka+SpringCloud Config+SpringCloud Bus。Nacos可以替代Eureka做服务注册中心,替代SpringCloud Config、Spri-ngCloud Bus做服务配置中心和消息中心,
2、Alibaba Sentinel:Sentinel是一个用于流量控制、熔断降级和系统负载保护的开源框架。
3、Alibaba RocketMQ:RocketMQ是一个分布式消息队列系统,可以实现高可靠性和高吞吐量的消息传递。
4、Alibaba Seata:Seata是一个用于分布式事务处理的解决方案。
5、Alibaba OSS:OSS是阿里云提供的对象存储服务,它可以与Spring Cloud一起使用,以实现文件存储和管理。
阻塞状态sleep与wait的区别
1、sleep()是Thread类的静态方法,wait()是Object类的实例方法
2、sleep()不会释放对象锁,wait()会释放对象锁
3、sleep()可以用在任何地方,wait()只能用在同步代码块中
sleep()就是当前线程进入阻塞状态,cpu不会继续执行当前线程,直到指定的时间超过才会重新执行当前线程,这个过程中不会释放对象锁,如果当前线程持有对象锁,那么其他需要此对象锁才能运行的线程就无法继续。
wait()是指在一个已经进入了同步代码块的线程让cpu停止执行当前线程转去执行其他线程,并且将当前线程所持有的对象锁释放,让其他需要此对象锁的线程能够正常运行,当其他线程调用notify()或notifyAll()时才会唤醒当前线程,但是并不会马上获得对象锁,只是进入就绪状态,准备抢锁。
什么情况下会导致索引失效,索引失效的原因
1、未使用索引字段进行查询
2、索引列使用了函数或表达式
3、使用了不等于(!= 或 <>)操作符
4、LIKE 操作符的模糊查询
5、对索引列进行了数据类型转换
6、使用 OR 连接多个条件
7、表中数据量较少
8、索引列上存在大量重复值
9、数据分布不均匀
10、索引列上存在过多的 NULL 值
11、索引字段与排序字段不匹配
12、索引列进行了隐式类型转换
Java集合,是对多个数据进行存储的结构,简称java容器
怎么解决超买超卖
1、每一个用户只能抢购一件商品的限制;在数据库减库存时加上库存数量判断,库存数量为0时阻止秒杀订单的生成。数据库加唯一索引:防止用户重复购买。SQL加库存数量判断:防止库存变为负数
2、将存库MySQL迁移到Redis中,所有的写操作放到内存中,由于Redis中不存在锁故不会出现互相等待,并且由于Redis的写性能和读性能都远高于MySQL,这就解决了高并发下的性能问题。然后通过队列等异步手段,将变化的数据异步写入到DB中。
如何用redis实现分布式锁
setnx(SET if Not eXists)命令、expire命令、getset命令、Lua脚本
如何解决高并发情况下的问题
1.负载均衡
负载均衡是指将多台服务器组成一个集群,通过某种策略将访问请求均匀地分发到各个服务器上,使每个服务器的负载均衡。负载均衡可以提高系统的可用性和性能。
2.缓存
缓存是将数据存储在高速缓存中,以便在需要时快速访问。缓存可以减少数据库的读写操作,从而提高系统的性能。可以使用内存缓存、分布式缓存等方式实现缓存功能。
3.数据库优化
数据库是高并发系统的瓶颈之一,因此对数据库进行优化是解决高并发问题的重要方法。可以通过分库分表、索引优化、SQL优化等方式来提高数据库的性能。
4.异步处理
异步处理是将处理请求放入消息队列中,由后台进程或线程异步处理,从而避免了同步处理带来的性能瓶颈。异步处理可以使用消息队列、定时任务等方式实现。
5.分布式架构
分布式架构是将系统拆分成多个独立的子系统,每个子系统都可以独立运行,从而提高系统的可扩展性和可用性。分布式架构可以使用微服务、分布式缓存等方式实现。
如何解决MySQL的慢查询
1、不使用子查询
2、读取适当的记录LIMIT M,N
3、分组统计可以禁止排序
4、禁止不必要的ORDER BY排序
5、尽量不要超过三个表join
6、在varchar字段上建立索引时,必须指定索引长度
7、不要使用 select *
8、排序请尽量使用升序
9、尽量使用数字型字段
10、避免索引失效
11、删除表所有记录请用 truncate,不要用 delete
12、存储过程和触发器设置
索引的数据结构是什么样的
二叉树、红黑树/AVL树、hash表、B树(B+树)。
二叉树特点是每个节点最多只能有两棵子树,且有左右之分。如果是顺序的插入数据,二叉树会退化成链表,那么查找其中的元素的时候,就会需要整体的遍历,显然不适合作为数据库的索引。
红黑树是一种平衡的二叉树。添加节点的时候,相比二叉树,节点间会进行自动的平衡,不会退化成链表,可以有效降低树的高度。但是红黑树本质还是二叉树,对于数据库来说,避免不了在数据量大的情况下,树的高度依然非常高的情况。
Hash表,对索引的key进行一次Hash计算就可以定位出数据存储的位置,查找效率非常高。
B树是一棵平衡的m路搜索树,它的子节点可以有多个,使得整颗树更加的扁平化。所有节点关键字是按递增次序排列,并遵循左小右大原则。B树(B+树)一般较多用在存储系统上,比如数据库或文件系统。
线程和进程的区别
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)
(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。
Mybatis的动态sql标签
1、<trim>:通过修剪 SQL 语句的开头和结尾来动态生成 SQL 片段。它可以用于去除不必要的 SQL 关键字或条件语句,并提供了一些属性来定义修剪规则。
2、<where>:用于在生成的 SQL 语句中添加 WHERE 子句。它可以自动处理条件语句的前缀,并在有条件语句存在时添加 WHERE 关键字。
3、<set>:用于在生成的 SQL 语句中添加 SET 子句。它主要用于更新操作,可以根据条件来动态生成需要更新的列。
4、<foreach>:用于在生成的 SQL 语句中进行循环操作。它可以遍历集合或数组,并根据指定的模板将集合元素或数组元素插入到 SQL 语句中。
5、<if>:用于在生成的 SQL 语句中添加条件判断。可以根据指定的条件决定是否包含某个 SQL 语句片段。
6、<choose>:类似于 Java 中的 switch 语句,根据条件选择执行不同的 SQL 语句片段。它可以包含多个 <when> 和一个可选的 <otherwise> 标签。
7、<when>:用于在 <choose> 标签中定义条件分支。可以根据指定的条件判断是否执行特定的 SQL 语句片段。
8、<otherwise>:在 <choose> 标签中可选的标签,用于定义当没有任何 <when> 条件匹配时执行的 SQL 语句片段。
9、<bind>:用于将表达式的结果绑定到一个变量上。可以在 SQL 语句中使用这个变量,避免重复计算表达式。
java垃圾回收机制的算法有哪些
1、标记-清除(Mark-Sweep)算法: 这是最基础的垃圾回收算法,分为两个阶段:首先标记出所有需要回收的对象,随后清除这些被标记的对象。此算法可能导致内存碎片化,影响后续的大对象分配。
2、复制(Copying)算法: 将内存区域分为两块,每次只使用其中一块。当一块区域用尽时,将存活的对象复制到另一块未使用的区域上,然后一次性清理掉之前的区域。这种方法可以有效避免内存碎片,但是空间利用率只有50%。
3、标记-整理(Mark-Compact)算法: 结合了标记-清除算法和复制算法的优点,同样先标记出需要回收的对象,但在清除阶段,它会将存活对象向一端移动,然后直接清理边界外的内存空间,从而解决了碎片化问题。
4、分代收集(Generational Collection)算法: 根据对象的生存周期将内存划分为年轻代和老年代。年轻代中对象生存期短,频繁回收,通常使用复制算法;老年代中对象生存期长,回收频率低,适合使用标记-清除或标记-整理算法。这种策略能够提高垃圾回收的效率,因为不同代上的对象特性不同,可以针对性地选择最适合的算法。
5、增量收集(Incremental GC): 试图减少垃圾回收的停顿时间,通过将垃圾回收过程分成多个小步骤,每次只回收一部分,使得程序可以间歇性地继续执行。
6、并发标记-清除(Concurrent Mark-Sweep, CMS): 在老年代中使用,尽可能地与应用程序并发执行标记和清除过程,减少垃圾回收引起的暂停时间,适用于对响应时间有严格要求的应用。
7、G1(Garbage First): 是一种针对大内存应用的垃圾收集器,将堆内存分割成多个大小相等的区域,并使用复制和标记-整理算法的混合策略,以低延迟为目标进行垃圾回收。G1能够预测并主动管理内存碎片,避免长时间的STW(Stop-The-World)事件。
新生代怎么到的老年代
1、Eden区满时,进行Minor GC
当Eden和一个Survivor区中依然存活的对象无法放入到Survivor中,则通过分配担保机制提前转移到老年代中。
2.、对象体积太大, 新生代无法容纳
-XX:PretenureSizeThreshold即对象的大小大于此值, 就会绕过新生代, 直接在老年代分配, 此参数只对Serial及ParNew两款收集器有效。
3、Survivor区空间不足:如果Survivor区中经历了多次GC后仍然存活的对象数量过多,以至于无法容纳在一个Survivor区时,部分对象也会被提前晋升到老年代,即使它们没有达到年龄阈值。
4、动态对象年龄判定
在某些情况下,如果Survivor区中的对象空间占用超过了某一比例(比如,survivor空间的50%被占用),那么年龄较大的对象也可能在未达到最大年龄阈值时就被晋升到老年代。
泛型常用特点
1、类型安全:泛型在编译时期就能进行类型检查,可以在编译阶段捕获一些类型错误,避免在运行时出现类型转换异常。这使得代码更加稳定、可靠。
2、代码重用:泛型允许编写可以应用于多种数据类型的通用代码,无需为每种类型重复编写相同的逻辑,增强了代码的复用性和模块化。
3、可读性:使用泛型能够使代码更加清晰易懂,通过在代码中指定类型参数,可以清晰地表达出方法或类的意图。
4、集合类型安全:泛型广泛应用于集合类,例如`ArrayList<E>`、`HashMap<K, V>`等,通过指定元素类型或键值对类型,在编译时能够发现类型不匹配的错误。
5、代码优化:泛型能够提高代码性能,在编译时进行类型检查和类型擦除,可以减少运行时的类型转换,提高执行效率。
6、增强代码可维护性:通过使用泛型,可以使代码更易于维护和扩展,减少了对类型的依赖性,使得代码更灵活。
AOP是什么
AOP是面向切面编程,是一种编程范式,用于解决软件开发中的横切关注点(Cross-cutting Concerns)问题。横切关注点是指那些遍布于整个应用程序的多个模块中的功能,它们与核心业务逻辑关联不大,但却会在很多不同的地方重复出现,例如日志记录、安全性验证、事务管理、异常处理等。
在传统的面向对象编程(OOP)中,关注点通常被封装在单个类或对象中,但这对于处理横切关注点来说不够高效,因为这些功能的代码往往会散落在各个业务逻辑类中,造成代码重复,难以维护。AOP通过将这些横切关注点从业务逻辑中分离出来,集中进行管理和织入,实现了关注点的解耦。
AOP的关键概念包括:
1、切面(Aspect):切面是跨越多个对象的行为或关注点的模块化,比如日志记录切面、事务管理切面等。它封装了横切关注点的实现。
2、连接点(Joinpoint):在程序执行过程中可以插入切面操作的点,如方法调用、异常抛出等。
3、通知(Advice):在切面的某个特定连接点上执行的动作。通知有多种形式,比如前置通知(在方法调用前执行)、后置通知(在方法调用后执行)、环绕通知(围绕方法调用执行)等。
4、切入点(Pointcut):定义了切面中的通知应该在哪些连接点上执行的规则。例如,一个切入点可以表达“所有业务层方法的执行”。
5、织入(Weaving):将切面应用到目标对象并创建代理对象的过程。织入可以在编译时、类加载时或运行时进行。
通过AOP,开发者可以更加专注于业务逻辑的实现,而将诸如日志、安全等横切关注点的处理交给AOP框架自动完成,从而提高了代码的模块化程度、可维护性和可重用性。Spring框架是Java领域中广泛使用的实现AOP概念的框架之一。
OOP是什么
OOP是指面向对象程序设计,是一种计算机编程架构。面向对象编程强调的是通过对象的相互作用来解决问题,模拟现实世界的实体关系,使得程序设计更加直观,易于理解,便于维护和扩展。许多现代编程语言如Java、C++、C#等都支持面向对象编程。
面向对象的三大特性:
1、封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。
2、继承:提高代码复用性;继承是多态的前提。
3、多态:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。
AOP与OOP的区别
OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。
AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。
1、面向目标不同:简单来说OOP是面向名词领域,AOP面向动词领域。
2、思想结构不同:OOP是纵向结构,AOP是横向结构。
3、注重方面不同:OOP注重业务逻辑单元的划分,AOP偏重业务处理过程的某个步骤或阶段。
重载与重写的含义与区别
重写(Overriding)是指在子类中重新定义一个与父类中同名、同参数列表的方法。重写的目的是为了实现多态性,子类可以重写父类中的方法,并且可以根据自己的需要进行修改或扩展。在重写中,子类方法的返回类型和参数列表必须与父类方法相同或者是其子类,而且子类方法的访问修饰符不能低于父类方法的访问修饰符。
重载(Overloading)是指在同一个类中,允许存在多个同名的方法,这些方法的参数列表必须不同。方法的返回类型、修饰符等可以不同,但这些不是重载的决定因素。编译器会根据方法调用时提供的参数类型和数量来决定调用哪个具体的方法。
区别总结
1、应用场景:重载用于同一类中方法功能相似但参数不同的情况,而重写用于子类修改或增强父类行为的情况。
2、方法签名:重载关注方法名相同但参数列表不同;重写要求方法名、参数列表及返回类型均与父类方法一致。
3、发生时间:重载的决定在编译期,属于静态绑定;重写则在运行时根据对象的实际类型确定,属于动态绑定。
4、访问权限与异常处理:重载对此没有特别限制;重写则要求访问权限不能更低,且抛出的异常不能比父类方法更广泛。
java多态的实现原理
Java中多态的实现原理主要基于以下几点核心概念:
1、继承(Inheritance):多态的实现基础是类的继承关系。一个类可以从父类继承属性和方法,同时可以扩展或覆盖父类的功能。
2、方法重写(Overriding):子类可以重写父类中的方法,提供自己的实现。这是多态表现的关键,允许子类对象对相同的请求做出不同的响应。
3、向上转型(Upcasting):将子类对象赋值给父类引用的过程。这实际上是一种隐式的类型转换,使得可以通过父类的引用调用子类重写的方法,从而实现多态行为。
4、动态绑定(Dynamic Binding)/ 运行时多态(Runtime Polymorphism):也称为晚期绑定。在Java中,非静态方法的调用(特别是被重写的方法)是在运行时绑定的。这意味着,决定调用哪个方法的实现是在程序运行时,根据对象的实际类型而非引用类型来决定。这一过程是由Java虚拟机(JVM)通过查阅对象的实际类型信息和虚方法表(Virtual Method Table, VMT)来实现的。
java的四种引用,强弱软虚用到的场景
1. 强引用(Strong Reference)
它是最常见的引用类型。当一个对象被一个强引用引用时,即使内存不足时,垃圾回收器也不会回收该对象。只有当该对象的所有强引用都被解除后,垃圾回收器才会回收该对象。强引用的应用场景通常是在对象的生命周期内都需要引用该对象的情况。
2. 软引用(Soft Reference)
软引用是一种相对较弱的引用类型。当一个对象被一个软引用引用时,只有当系统内存不足时,垃圾回收器才会回收该对象。软引用通常用来实现缓存或者高速缓存,当内存不足时可以释放一些缓存的对象。
3. 弱引用(Weak Reference)
弱引用也是一种相对较弱的引用类型。当一个对象被一个弱引用引用时,无论内存是否足够,垃圾回收器都可能回收该对象。弱引用通常用来实现一些特定的功能,如观察者模式。
4. 虚引用(Phantom Reference)
虚引用是最弱的引用类型。当一个对象被一个虚引用引用时,该对象在任何时候都可能被垃圾回收器回收。虚引用主要用于管理直接内存,当虚引用被回收时,可以触发一些特定的清理操作。
JVM流程
1、类加载器初始化:
JVM启动时,首先初始化Bootstrap ClassLoader(启动类加载器),它负责加载JVM自身需要的核心类(位于<JAVA_HOME>/jre/lib/rt.jar等位置)。随后,Extension ClassLoader(扩展类加载器)和Application ClassLoader(系统类加载器)也会被初始化,分别负责加载扩展类库和应用程序类路径上的类。
2、执行入口方法:
JVM会寻找并执行包含main方法的类,这个类通常由用户指定(比如通过命令行参数指定java MyClass)。main方法是Java应用程序的起点。
3、内存区域分配:
JVM会为运行的Java程序分配内存区域,包括堆(Heap)、栈(Stack)、方法区(Method Area/PermGen或Metaspace)、程序计数器(Program Counter Register)、本地方法栈(Native Method Stack)等。
4、类加载与初始化:
根据程序的需要,类加载器会逐步加载并链接(验证、准备、解析)所需的类,并进行类的初始化(执行类的静态初始化块和静态变量赋值)。
5、字节码解释执行或即时编译:
JVM读取类文件中的字节码,通过解释器逐条解释执行,或使用Just-In-Time (JIT) 编译器将热点代码编译成本地机器码以提高执行效率。
6、垃圾回收:
在程序运行过程中,JVM会自动管理内存,通过垃圾回收机制(GC)定期回收不再使用的对象所占用的内存空间,以保持内存的有效利用。
7、执行结束:
当main方法执行完毕,或者程序因异常退出,JVM开始关闭过程,包括执行所有已注册的Shutdown Hooks(关闭钩子),执行垃圾回收以回收剩余资源,最后JVM进程结束。
JVM调优
JVM(Java Virtual Machine)调优是指为了提高Java应用程序的性能,对Java虚拟机的配置参数和运行环境进行调整的过程。调优的目标通常包括减少内存消耗、提升应用响应速度、优化垃圾回收效率等。
堆和栈的区别
1、管理方式不同:栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;
2、空间大小不同:每个进程拥有的栈大小要远远小于堆大小。理论上,进程可申请的堆大小为虚拟内存大小,进程栈的大小 64bits 的 Windows 默认 1MB,64bits 的 Linux 默认 10MB;
3、生长方向不同:堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。
4、分配方式不同:堆都是动态分配的,没有静态分配的堆。栈有 2 种分配方式:静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca()函数分配,但是栈的动态分配和堆是不同的,它的动态分配是由操作系统进行释放,无需我们手工实现。
5、存储内容的不同:栈在函数调用时,函数调用语句的下一条可执行语句的地址第一个进栈,然后函数的各个参数进栈,其中静态变量是不入栈的。而堆一般是在头部用一个字节存放堆的大小,堆中的具体内容是人为安排;
6、申请效率的不同:栈由系统自动分配,速度较快,而堆一般速度比较慢;
Eureka服务注册是什么
Eureka服务注册是一种服务发现机制,主要用于微服务架构中,以实现服务实例的自动注册与发现。它是Netflix开发的一款开源组件,现已被Spring Cloud集成并广泛应用于微服务生态中。
什么是SpringCloudRibbon
Spring Cloud Ribbon 是 Spring Cloud 生态系统中的一部分,它基于 Netflix Ribbon 实现,是一个客户端侧的负载均衡器。Ribbon 允许开发者在微服务架构中以客户端的方式实现负载均衡策略,从而透明地在多个服务实例之间分配请求。
1、Ribbon和Nginx负载均衡区别:
当后端服务是集群的情况下,前端页面调用后端请求,要做负载均衡的话,常用的就是Nginx。
Ribbon主要是在服务端内做负载均衡,举例:订单后端服务 要调用 支付后端服务,这属于后端之间的服务调用,压根根本不经过页面,而支付后端服务是集群,这时候订单服务就需要做负载均衡来调用支付服务,记住是订单服务做负载均衡 来调用 支付服务。
RabbitMQ消息处理流程
1、生产者发送:应用(生产者)发送消息到RabbitMQ服务器的一个Exchange(交换机),指定Routing Key(路由键)来指示消息应如何被路由。
2、交换机路由:Exchange根据Routing Key和自身类型(如Direct, Fanout, Topic等)规则,将消息路由到一个或多个Queue(队列)。
3、消息入队:消息被投递到对应的队列中存储,等待消费者处理。队列可以被配置为持久化,确保消息在服务器重启后仍能保留。
4、消费者订阅:应用(消费者)通过创建Channel(信道)订阅队列,准备接收消息。
5、消息分发与确认:RabbitMQ将队列中的消息分发给消费者,消费者处理后,通过ACK(确认)通知RabbitMQ消息已被成功处理,之后RabbitMQ可从队列中删除该消息。若未收到ACK且配置允许,RabbitMQ可能重发消息以确保消息至少被处理一次。
消息如何分发
1、生产者将消息发送至交换机,并指定路由键。
2、交换机依据类型(如直连、扇形、主题等)和路由键,决定将消息投递给哪些队列。
3、队列累积消息,等待消费者订阅。
4、消费者通过连接通道订阅队列,接收消息。
5、消息可采用轮询或公平分发等策略,由RabbitMQ分发给消费者。
6、消费者处理后,向RabbitMQ发送确认(ACK),确认后消息可从队列删除。
消息分发通常指的是消息如何从生产者(PubISner)发送到RabbitMQ服务器,并最终到达一个或多个队列的过程。
1.直接分发:生产者将消息直接发送到指定的队列中。
2.交换机分发:生产者将消息发送到交换机(Exchange),然后由交换机根据路由规则将消息路由到一个或多个队列。
消息路由是指消息在RabbitMQ内部的传递过程,这个过程涉及到交换机(Exchange)和队列(Queue)之间的绑定(Binding)关系。
1.路由键(Routing Key):当消息到达交换机时,通常会附带一个路由键。交换机根据这个路由键来决定如何将消息路由到队列。
2.绑定键(Binding Key):当队列绑定到交换机时,会指定一个绑定键。只有当消息的路由键与绑定键匹配时,消息才会被路由到该队列。
微服务框架的六种常用设计模式是什么
详解:https://blog.csdn.net/yeq2014/article/details/135734483
1.聚合器微服务设计模式
一种设计模式,用于通过聚合多个独立的微服务的响应来组成一个复杂的服务, 它可以是一个简单的Web页面,将检索到的数据进行处理展示。它也可以是一个更高层次的组合微服务,对检索到的数据增加业务逻辑后进一步发布成一个新的微服务,这符合DRY原则。
2.链式微服务设计模式
在此模式中,一个微服务的输出作为下一个微服务的输入,形成一个处理链。适合需要顺序执行多个服务操作的场景,每个步骤基于前一步的结果。
3.分支微服务设计模式
分支微服务设计模式是一种将复杂的业务逻辑拆解为多个微服务的架构设计模式。在该设计模式中,每个微服务负责处理不同的分支逻辑,即根据不同条件或参数的取值来执行不同的业务流程。
4.代理微服务设计模式
代理微服务设计模式是一种常用的微服务架构模式,用于提供对其他微服务的访问和控制。该模式的核心思想是通过引入代理服务来隐藏底层微服务的复杂性,并提供额外的功能和保护
5.异步消息传递微服务设计模式
异步消息传递微服务设计模式是一种架构模式,用于实现松耦合、高可扩展性和可靠性的微服务系统。在这种模式下,微服务之间通过消息队列或消息中间件进行通信,将消息作为传递机制,实现服务之间的解耦和异步通信。虽然REST设计模式非常流行,但它是同步的,会造成阻塞。
6.数据共享微服务设计模式
数据共享微服务设计模式是一种架构模式,旨在实现不同微服务之间有效地共享数据。在微服务架构中,每个微服务负责管理自己的数据,但有时候需要在多个微服务之间共享数据,这时候就需要使用数据共享微服务设计模式。
什么是TCP/IP和UDP
TCP/IP和UDP都是Internet协议套件中的传输层协议,负责在网络中端到端地传输数据。
1、TCP/IP (传输控制协议)
面向连接:在数据传输前,TCP要求建立一个连接,通过三次握手过程确保两端准备好通信。连接建立后,双方可以进行双向数据传输。
可靠性:TCP提供了高度的可靠性,通过序列号、确认应答、重传机制、错误校验以及流量控制等手段,确保数据正确无误、有序地到达目的地。
有序传输:TCP保证数据包按照发送顺序到达接收方,即使在网络中这些包可能以不同的顺序到达。
流控:TCP具有流量控制功能,可以防止发送方过快发送数据导致接收方无法处理,通过滑动窗口机制动态调整发送速率。
全双工:支持同时双向数据传输。
2、UDP (用户数据报协议)
无连接:UDP不建立连接,发送数据前无需握手过程,减少了延迟,但也不保证数据一定能到达对方。
不可靠:UDP不负责数据包的重传和错误校验,数据可能丢失、重复或乱序,适合对实时性要求高而对数据完整性要求较低的应用。
速度快:由于省去了建立连接和确认的过程,UDP的数据传输通常比TCP更快。
头部开销小:UDP头部只有8字节,而TCP头部至少20字节,这使得UDP在传输小数据包时更为高效。
多播和广播:UDP支持多播和广播,能够一次性向多个目标发送数据,适用于如实时音视频传输、DNS查询等场景。
应用场景:
1、TCP常用于需要高可靠性的应用,如Web浏览(HTTP/HTTPS)、电子邮件(SMTP/POP3/IMAP)、文件传输(FTP)、在线交易等。
2、UDP适用于对实时性要求较高、容许一定丢包的场景,如即时通讯、在线游戏、VoIP、视频流、DNS查询等。
什么是TCP的三次握手
在网络数据传输中,传输层协议TCP(传输控制协议)是建立连接的可靠传输,TCP建立连接的过程,我们称为三次握手。
第一次,客户端向服务器发送SYN同步报文段,请求建立连接
第二次,服务器客户端的连接请求进行确认收到,并向客户端发送SYN同步报文,向客户端建立连接
客户端收到服务器端的确认请求 + 建立连接请求后处于连接状态,客户端先处于建立连接状态
第三次,客户端向服务端发送确认请求
服务器收到客户端的确认也处于连接状态,服务端后处于建立连接状态
http和https的区别
1、安全性:
1、http是未加密的协议,数据以明文形式传输,容易被截取和窃听,不适合传输敏感信息。
2、https则是加密的协议,它在http的基础上加入了SSL/TLS协议层,对传输的数据进行加密,可以有效防止数据在传输过程中被窃取或篡改,适合传输敏感信息,如银行账户、个人数据等。
2、端口:
1、http默认使用80端口。
2、https默认使用443端口。
3、网站申请流程不同:
1、http连接无需数字证书。http页面响应速度比https快。
2、https协议需要到CA申请证书,一般免费证书很少,需要交费,web服务器启用SSL需要获得一个服务器证书并将该证书与要使用的SSL的服务器绑定。
4、连接过程的不同
http的连接很简单,是无状态的,无状态是指服务器不知道客户端是什么状态。无状态的原因:每次请求都是独立的,上一次请求和下一次请求互不相干。
动态代理跟静态代理的区别
生成时间:
1、静态代理:在程序运行前就创建好代理类。
2、动态代理:在程序运行时由系统自动创建。
灵活性:
1、静态代理:固定的,为特定接口或类服务,修改需调整代理类代码。
2、动态代理:更灵活,可为多个接口动态处理,易于应对接口变化。
代码维护:
1、静态代理:可能产生代码重复,每个代理类单独编写。
2、动态代理:减少代码重复,代理逻辑集中,易于维护。
应用场景:
1、静态代理:适用于关系明确、不常变的场景。
2、动态代理:适合代理关系多变、需动态处理逻辑的场景,如AOP、网络请求等。
简而言之,静态代理事先编写好,改动成本较高但执行效率稳定;动态代理按需创建,适应性强但初始化有轻微性能开销。
设计模式的六大原则
设计模式的六大原则是面向对象设计和软件开发中的核心指导方针,旨在提高代码的可维护性、可扩展性和灵活性。以下是这六大原则的概述:
1、单一职责原则 (Single Responsibility Principle, SRP):
原则说明:一个类或者模块应该有且仅有一个引起它变化的原因。换句话说,一个类应该只负责一项职责,这样当需求变化时,修改的影响范围就会减小。
2、开放封闭原则 (Open/Closed Principle, OCP):
原则说明:软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着在不修改原有代码的情况下,可以容易地扩展功能。
3、里氏替换原则 (Liskov Substitution Principle, LSP):
原则说明:子类应当能够替换其基类并在软件中正确运行,而不影响程序的正确性。换句话说,子类应保持父类的行为约定。
4、依赖倒置原则 (Dependency Inversion Principle, DIP):
原则说明:高层模块不应该依赖于低层模块,两者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。鼓励使用接口和抽象类来降低耦合度。
5、接口隔离原则 (Interface Segregation Principle, ISP):
原则说明:客户端不应该被迫依赖它不需要的接口。接口应该尽可能细化,以满足客户端的特定需求,避免大而全的接口。
6、迪米特法则 (Law of Demeter, LoD) 或称最少知识原则:
原则说明:一个对象应当对其他对象有最少的了解。也就是说,一个类应该只和它的朋友(直接的朋友或通过参数传递的对象)交流,不和朋友的朋友交流,以减少耦合。
简述什么是单例模式
详解:https://blog.csdn.net/weixin_57504474/article/details/124494554
单例模式是一种软件设计模式,其核心在于确保一个类在整个应用程序的生命周期中仅有一个实例,并提供一个全局访问点来获取这个实例。
简述什么是工厂模式
详解:https://blog.csdn.net/yiridancan/article/details/137033767
工厂模式(Factory Pattern)是Java中一种常见的设计模式,属于创建型模式的一种。它用于创建对象,但与直接在代码中使用new关键字创建对象不同,工厂模式通过一个共同的接口来创建对象,从而将对象的创建过程与具体的使用客户端代码分离开来。
垃圾回收机制是什么
GC(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制。可以有效的防止内存泄露、保证内存的有效使用,也减轻了 Java 程序员的对内存管理的工作量。
什么是内存溢出和内存泄露
详解:https://blog.csdn.net/qq_37933128/article/details/126969220
内存溢出指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出。
内存泄漏是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。
类的加载机制
类的加载指的是Java虚拟机(JVM)将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。
Mysql中InooDB支持的四种事务隔离级别
1、读未提交(Read Uncommitted)
在这个隔离级别下,一个事务可以读取到另一个事务未提交的修改。这种情况下可能会发生“脏读”(dirty read),即读取到的数据可能是其他事务已经修改但还未提交的数据,如果那个事务最终回滚,那么读取的数据就是无效的。
2、读已提交(Read Committed)
这个级别保证了一个事务只能读取到已经提交的事务所做的修改。它避免了脏读的问题,但是可能会导致“不可重复读”(non-repeatable read),即在同一个事务中,如果两次读取同一行数据,可能得到不同的结果,因为在这两次读取之间,可能有其他事务提交了对该行数据的修改。
3、可重复读(Repeatable Read)
InnoDB的默认事务隔离级别。在这个级别下,同一个事务内多次读取同一行数据的结果是一致的,即使有其他事务在这期间对数据进行了修改并提交。这避免了不可重复读的问题。理论上,这个级别下仍可能发生“幻读”(phantom read),即同一事务内两次执行相同的查询,第二次查询可能返回第一次查询未出现的新行,但由于InnoDB的行级锁和Next-Key Locks机制,实际上在InnoDB中幻读得到了解决。
4、串行化(Serializable)
这是最高的事务隔离级别,通过锁定事务访问的表来防止并发问题的发生。在这种级别下,事务按照顺序依次执行,仿佛是串行的一样,可以避免脏读、不可重复读和幻读等问题,但会导致大量的超时和锁争用,因此性能开销最大。
什么是控制反转IOC,如何使用?
控制反转(Inversion of Control,简称IOC)是一种设计思想,其核心是将原本由代码直接操控的对象的调用权交给第三方(如Spring容器)来控制。在Spring框架中,IOC容器负责创建对象、管理对象之间的关系,并在运行时将这些对象注入到需要它们的组件中。
实现方式:
Spring框架通过依赖注入(Dependency Injection,简称DI)的方式实现控制反转。依赖注入有三种主要方式:构造器注入、属性注入(Setter注入)和方法注入。其中,构造器注入和属性注入在Spring中最为常用。
优势:
1、解耦:通过Spring容器管理Bean之间的依赖关系,代码不再直接依赖于具体的实现类,降低了代码之间的耦合度。
2、易于测试:由于依赖关系被外部化到Spring容器中,可以方便地替换依赖组件的实现,以支持单元测试或集成测试。
3、提高可维护性和可扩展性:当需要修改或扩展系统功能时,只需修改Spring容器的配置,而无需修改代码。
项目中如何应用:详解:Spring核心之控制反转(IOC)详解以及项目中是如何应用的_控制反转ioc使用场景-CSDN博客
什么是循环依赖
在 Spring 应用中,循环依赖指的是两个或多个 Bean 之间相互引用,造成了一个环状的依赖关系。
循环依赖的原因:通常是由于错误的 Bean 配置或者设计不佳引起的。以下是几个可能导致循环依赖的原因:
1、构造函数的循环依赖: 当一个 Bean 的构造函数依赖于另一个 Bean,而同时这个另一个 Bean 的构造函数也依赖于第一个 Bean,就会出现循环依赖。
2、单例模式的循环依赖: 如果两个单例 Bean 相互依赖,Spring 在创建这两个 Bean 时可能会遇到问题。
3、错误的依赖注入方式: 如果使用了错误的注入方式,比如字段注入或者方法注入,在某些情况下可能会导致循环依赖。
如何解决循环依赖问题?
在 Spring Boot 中,可以采取一些方法来解决循环依赖问题:
1、构造函数注入: 首选的依赖注入方式是使用构造函数注入。通过在构造函数中注入依赖,可以避免循环依赖问题。
2、Lazy Initialization(懒加载): 可以尝试使用懒加载来延迟 Bean 的初始化。这可以通过 @Lazy 注解来实现,将 Bean 的初始化推迟到首次使用时进行。
3、重新设计应用结构: 如果可能的话,重新设计应用的架构,尽量减少相互依赖,或者将依赖关系拆分为更小的单元,以减少循环依赖的可能性。
4、使用 Setter 注入: 在某些情况下,使用 Setter 方法进行注入可以避免循环依赖。通过 Setter 方法注入可以延迟依赖注入的时机。
如何通过AOP实现防止重复提交
- 定义自定义注解:
首先,定义一个自定义注解,用于标记那些需要防止重复提交的方法。例如,可以创建一个名为@NoRepeatSubmit的注解
- 实现切面
创建一个切面类,该类负责处理标记了@NoRepeatSubmit注解的方法调用。在切面中,你需要在方法执行前后添加逻辑,以检查和记录请求是否重复。
- 应用自定义注解
在需要防止重复提交的Controller方法上使用自定义的@NoRepeatSubmit注解。
Nginx 怎么处理请求的?
https://blog.csdn.net/qq_33240556/article/details/136901666
Nginx 常用命令有哪些?
启动: nginx 。
停止: nginx -s stop 或 nginx -s quit 。
重启: nginx -s reload 或 service nginx reload 。
重载指定配置文件: .nginx -c /usr/local/nginx/conf/nginx.conf 。
查看nginx版本: nginx -v 。大写-V 显示版本号及编译时的配置选项
相关文章:

程序员高频率面试题-整理篇
Redis 除了做缓存,还能做什么? 分布式锁:通过 Redis 来做分布式锁是一种比较常见的方式。通常情况下,我们都是基于 Redisson 来实现分布式锁。 限流:一般是通过 Redis Lua 脚本的方式来实现限流。 消息队列&#x…...

第二十二章 TCP 客户端 服务器通信 - TCP设备的OPEN和USE命令关键字
文章目录 第二十二章 TCP 客户端 服务器通信 - TCP设备的OPEN和USE命令关键字TCP设备的OPEN和USE命令关键字TCP设备的OPEN和USE命令关键字 第二十二章 TCP 客户端 服务器通信 - TCP设备的OPEN和USE命令关键字 TCP设备的OPEN和USE命令关键字 可以使用位置参数(如上所述)或关键…...

CSS 语法规范
基本语法结构 CSS 的基本语法结构包含 选择器 和 声明块,两者共同组成 规则集。规则集可以为 HTML 元素设置样式,使页面结构和样式实现分离,便于网页的美化和布局调整。 CSS 规则集的结构如下: selector {property: value; }选择器(Selector) 选择器用于指定需要应用…...

Linux开发常用命令
文章目录 开发常用命令包管理 网络操作用户和权限系统监控nohup和screen的区别 开发常用命令 Linux开发中常用的命令非常多,以下是一些基本且重要的命令,这些命令对于日常的开发工作流程至关重要: 文件和目录操作 ls:列出目录内…...

Linux第92步_如何编写“设备树”下的platform设备驱动
Linux字符设备驱动,新字符设备驱动和设备树下的GPIO驱动,都是配置IO引脚所使用的GPIO寄存器,驱动开发方式和裸机没啥区别。Limux内核提供了pinctrl和gpio子系统用于GPIO驱动,借助它可简化GPIO驱动开发。 对GPIO进行读写操作&#…...

从零开始学习 sg200x 多核开发之 eth0 MAC 地址修改
在 sophpi 中,默认网卡 eth0 的 MAC 地址未配置,是随机生成的。这样就会导致每次重启之后,MAC 地址会改变,从而导致通过 DHCP 获取 IP 地址每次也都在变化。 查看 MAC 地址 前文提到 eth0 自动使能并通过 DHCP 获取 IP 地址&…...

JMeter与大模型融合应用之JMeter日志分析服务化实战应用
JMeter与大模型融合应用之JMeter日志分析服务化 引言 在当今的互联网时代,网站和应用程序的性能直接影响到用户的体验和业务的成功。为了保证系统的稳定性和高效性,性能测试成为了软件开发过程中的一个重要环节。在这其中,Apache JMeter作为一款开源的性能测试工具,凭借其…...

AtCoder Beginner Contest 380(A-F)
比赛链接:AtCoder Beginner Contest 380(A-F) A - 123233 题意 给出一个数字 N N N,问这个数字中是否 1 1 1 恰好出现了 1 1 1 次, 2 2 2 恰好出现了 2 2 2 次, 3 3 3 恰好出现了 3 3 3 次。 数据范围 100000 ≤ N ≤ 99…...

多线程-阻塞队列
目录 阻塞队列 消息队列 阻塞队列用于生产者消费者模型 概念 实现原理 生产者消费者主要优势 缺陷 阻塞队列的实现 1.写一个普通队列 2.加上线程安全和阻塞等待 3.解决代码中的问题 阻塞队列 阻塞队列,是带有线程安全功能的队列,拥有队列先进…...

el-table合并单元格之后,再进行隔行换色的且覆盖表格行鼠标移入的背景色的实现
el-table 中有现成的隔行换色功能,只要增加 stripe 属性即可。但是如果有单元格合并的话,这个属性就不可用了。这时候我们就需要动点小心思了。 基于相同字段进行合并 单元格合并:基于表头中的某一列,具有相同值的个数相加进行合…...

java模拟键盘实现selenium上下左右键 table中的左右滚动条实现滚动
在这篇文章中,我们将学习如何使用Java编程语言模拟键盘输入,特别是模拟上下左右方向键的操作。这是一个很有趣的项目,尤其适合刚入行的开发者。我们将分步进行,接下来,我们会通过表格展示整个实现过程,然后…...

SDF,一个从1978年运行至今的公共Unix Shell
关于SDF 最近发现了一个很古老的公共Unix Shell服务器,这个项目从1978年运行至今,如果对操作系统,对Unix感兴趣,可以进去玩一玩体验一下 SDF Public Access UNIX System - Free Shell Account and Shell Access 注册方式 我一…...

前馈神经网络 (Feedforward Neural Network, FNN)
代码功能 网络定义: 使用 torch.nn 构建了一个简单的前馈神经网络。 隐藏层使用 ReLU 激活函数,输出层使用 Sigmoid 函数(适用于二分类问题)。 数据生成: 使用经典的 XOR 问题作为数据集。 数据点为二维输入ÿ…...

【Python进阶】Python中的数据库交互:使用SQLite进行本地数据存储
1、数据持久化与访问效率 数据持久化是指程序运行过程中产生的数据能够长期保存,即使程序关闭或系统重启后仍可读取和修改。通过数据库,我们可以确保数据持久化的同时,实现数据的快速访问。例如,银行系统需要实时更新账户余额&am…...

ZooKeeper单机、集群模式搭建教程
单点配置 ZooKeeper在启动的时候,默认会读取/conf/zoo.cfg配置文件,该文件缺失会报错。因此,我们需要在将容器/conf/挂载出来,在制定的目录下,添加zoo.cfg文件。 zoo.cfg logback.xml 配置文件的信息可以从二进制包…...

函数指针示例
目录: 代码: main.c #include <stdio.h> #include <stdlib.h>int Max(int x, int y); int Min(int x, int y);int main(int argc, char**argv) {int x,y;scanf("%d",&x);scanf("%d",&y);int select;printf(&q…...

vue如何实现组件切换
一、使用条件渲染 (v-if) <template><div><button click"currentView ComponentA">Show Component A</button><button click"currentView ComponentB">Show Component B</button><component-a v-if"curren…...

计算机视觉 1-8章 (硕士)
文章目录 零、前言1.先行课程:python、深度学习、数字图像处理2.查文献3.环境安装 第一章:概论1.计算机视觉的概念2.机器学习 第二章:图像处理相关基础1.图像的概念2.图像处理3.滤波器4.卷积神经网络CNN5.图像的多层表示:图像金字…...

整数唯一分解定理
整数唯一分解定理,也称为算术基本定理,是由德国数学家高斯在其著作《算术研究》中首次提出的。本文回顾整数唯一分解定理以及对应的几个重要结论。 一、整数唯一分解定理 整数唯一分解定理,也称为算术基本定理,是数论中的一个重…...

Grass脚本2倍速多账号
前言,小编也是第一次撸空投,我是抱着试一试的态度,梦想总是要有的万一白嫖了呢 Grass 是什么? Grass 扩展程序是一款创新的工具,它可以帮助您释放未使用的网络资源的力量。 通过分享您的剩余带宽,您可以赚…...

15分钟学 Go 第 56 天:架构设计基本原则
第56天:架构设计基本原则 学习目标 理解和掌握基本的架构设计原则,以提升软件系统的可维护性、可扩展性和可重用性。 内容提纲 架构设计原则概述常见架构设计原则 单一职责原则 (SRP)开放/封闭原则 (OCP)里氏替换原则 (LSP)接口分离原则 (ISP)依赖反…...

HTML5 Video(视频)
HTML5 Video(视频) HTML5视频是现代网页设计中不可或缺的一部分,它允许开发者在网页中嵌入视频内容,为用户提供丰富多样的媒体体验。本文将深入探讨HTML5视频的各个方面,包括其基本用法、支持的格式、自定义播放器、浏览器兼容性以及最佳实践。 一、HTML5视频的基本用法 …...

开源模型应用落地-qwen模型小试-Qwen2.5-7B-Instruct-tool usage入门-串行调用多个tools(三)
一、前言 Qwen-Agent 是一个利用开源语言模型Qwen的工具使用、规划和记忆功能的框架。其模块化设计允许开发人员创建具有特定功能的定制代理,为各种应用程序提供了坚实的基础。同时,开发者可以利用 Qwen-Agent 的原子组件构建智能代理,以理解和响应用户查询。 本篇将介绍如何…...

MySQL:表设计
表的设计 从需求中获得类,类对应到数据库中的实体,实体在数据库中表现为一张一张的表,类中的属性就对应着表中的字段(也就是表中的列) 表设计的三大范式: 在数据库设计中,三大范式࿰…...

173. 二叉搜索树迭代器【 力扣(LeetCode) 】
文章目录 零、原题链接一、题目描述二、测试用例三、解题思路四、参考代码 零、原题链接 173. 二叉搜索树迭代器 一、题目描述 实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器: BSTIterato…...

大三学生实习面试经历(1)
最近听了一位学长的建议,不能等一切都准备好再去开始,于是就开始了简历投递,恰好简历过了某小厂的初筛,开启了线上面试,记录了一些问题: (通过面试也确实了解到了自己在某些方面确实做的还不够…...

【论文复现】STM32设计的物联网智能鱼缸
📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀STM32设计的物联网智能鱼缸 【1】项目功能介绍【2】设计需求总结【3】项目硬件模块组成 1.2 设计思路【1】整体设计思路【2】ESP8266工作模式…...

常见长选项和短选项对应表
长选项和短选项的等效形式 在命令行工具中,这种长选项(如--delete)和短选项(如-d)等效的情况很常见。例如--verbose和-v(用于输出详细信息),--quiet和-q(用于安静模式&a…...

Ubuntu24 上安装搜狗输入法
link 首先在终端中依次输入以下代码 sudo apt update sudo apt install fcitx 找到语言支持 在终端中依次输入 sudo cp /usr/share/applications/fcitx.desktop /etc/xdg/autostart/ sudo apt purge ibus 进入网页 搜狗输入法linux-首页 shurufa.sogou.com/linux 找到刚才下…...

【AI图像生成网站Golang】JWT认证与令牌桶算法
AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与调试(等待更新) 三、JWT认证与令牌桶算法 在现代后端开发中,用户认证和接口限流是确保系统安全性和性能的两大关键要素…...