RabbitMQ 中的六大工作模式介紹與使用

文章目錄

    • 簡單隊列(Simple Queue)模式
      • 配置類定義
      • 消費者定義
      • 發送消息測試消費
    • 工作隊列(Work Queues)模式
      • 配置類定義
      • 消費者定義
      • 發送消息測試消費
      • 負載均衡調優
    • 發布/訂閱(Publish/Subscribe)模式
      • 配置類定義
      • 消費者定義
      • 發送消息測試消費
    • 路由(Routing)模式
      • 配置類定義
      • 消費者定義
      • 發送消費測試消費
    • 主題(Topics)模式
      • 配置類定義
      • 消費者定義
      • 發送消息測試消費
    • RPC(Remote Procedure Call)模式
      • 配置類定義
      • 請求與響應實體類
      • 消費者定義
      • 發送消息測試消費

簡單隊列(Simple Queue)模式

  • 結構:一個生產者對應一個消費者,生產者將消息發送到指定隊列,消費者從該隊列獲取消息。
  • 工作流程:生產者創建一個消息并發送到 RabbitMQ 的隊列中,消費者從這個隊列里取出消息進行處理。
  • 應用場景:適用于任務處理邏輯簡單,對消息處理速度要求不高,且消息處理順序要求不嚴格的場景,比如簡單的日志收集系統。

以下是簡單隊列(Simple Queue)模式的使用案例。

配置類定義

package test;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class SimpleQueueConfig {@Beanpublic DirectExchange simpleQueueExchange() {return ExchangeBuilder// 指定名稱為simple-queue-exchange的交換機.directExchange("simple-queue-exchange")// 聲明為持久化交換機.durable(true).build();}@Beanpublic Queue simpleQueue() {return QueueBuilder// 指定一個名稱為simple-queue的持久化隊列.durable("simple-queue").build();}@Beanpublic Binding simpleQueueToSimpleQueueExchangebinding() {// 綁定隊列給交換機,根據隊列名為路由鍵return BindingBuilder.bind(simpleQueue()).to(simpleQueueExchange()).withQueueName();}}

消費者定義

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;@Component
@Slf4j
public class SimpleQueueConsumer {@RabbitListener(queues = "simple-queue")public void consumer(String message) {log.info("消費者接收消息:{}", message);}}

發送消息測試消費

package test;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);rabbitTemplate.convertAndSend("simple-queue", "hello world!");}}

控制臺輸出:

在這里插入圖片描述

工作隊列(Work Queues)模式

  • 結構:一個生產者對應多個消費者,多個消費者共同從一個隊列中獲取消息進行處理。
  • 工作流程:生產者將消息發送到隊列,多個消費者從該隊列中獲取消息(默認采用輪詢的負載均衡策略),一條消息只會被一個消費者處理。
  • 應用場景:適用于需要將大量任務分發給多個工作者并行處理的場景,例如訂單處理、圖片處理等。

以下是工作隊列(Work Queues)模式的使用案例。

配置類定義

定義一個 DirectExchange 類型的交換機與兩個隊列,通過隊列名作為 RoutingKey 進行綁定。

package test;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class WorkQueueConfig {@Beanpublic DirectExchange workQueueExchange(){return ExchangeBuilder.directExchange("work-queue-exchange").durable(true).build();}@Beanpublic Queue workQueue(){return QueueBuilder.durable("work-queue").build();}@Beanpublic Binding workQueueToWorkQueueExchangeBinding(){return BindingBuilder.bind(workQueue()).to(workQueueExchange()).withQueueName();}}

消費者定義

定義兩個消費者,分別監聽兩個不同的隊列。

消費者 1:

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class WorkQueueConsumer01 {@RabbitListener(queues = "work-queue")public void receive(String message){log.info("WorkQueueConsumer01 receive a message:{}",message);}}

消費者 2:

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class WorkQueueConsumer02 {@RabbitListener(queues = "work-queue")public void receive(String message){log.info("WorkQueueConsumer02 receive a message:{}",message);}}

發送消息測試消費

work-queue-exchange 交換機中發送 10 條消息。

package test;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);for (int i = 0; i < 10; i++) {rabbitTemplate.convertAndSend("work-queue-exchange", "work-queue", "hello world!" + i);}}}

控制臺輸出:

在這里插入圖片描述

在上例結果,消費者 1 與消費者 2 對消息進行了輪詢處理。

負載均衡調優

在工作隊列模式下,多個消費者處理消息默認按照輪詢的規則進行處理。但是如果其中某個消費者的處理能力比其他消費者更為強大,那么它實際上可以處理更多的消息,如果此時還是按照輪詢規則來處理消息,這樣是對該消費者能力的一種浪費。

對于上述情況,在 RabbitMQ 中支持調整消費者處理消息時的負載均衡策略,具體而言,即通過設置預取數量(prefetch count)參數,以實現更靈活的消息分發策略,即讓處理能力更強大的消費者處理更多的消息。

在 Spring Boot 中,可以通過設置 spring.rabbitmq.listener.simple.prefetch 參數來控制消費者的預取數量:

spring:rabbitmq:listener:simple:prefetch: 1

將預取數量設置為 1,則每個消費者在處理完當前消息并確認(ACK)之后才會接收下一條消息,從而避免了某個消費者負載過重的情況。

模擬當某個消費者處理能力較弱:

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class WorkQueueConsumer01 {@RabbitListener(queues = "work-queue")public void receive(String message) throws InterruptedException {// 模擬WorkQueueConsumer01處理能力較弱Thread.sleep(1);log.info("WorkQueueConsumer01 receive a message:{}",message);}}

再次向交換機發送 10 條消息,控制臺輸出:

在這里插入圖片描述

在上述結果中,由于 WorkQueueConsumer01 處理消息的能力更弱,所以更多的消息被分攤到了 WorkQueueConsumer02 處理。

發布/訂閱(Publish/Subscribe)模式

  • 結構:包含一個生產者、一個交換機(Exchange)和多個隊列,多個消費者分別監聽不同的隊列。
  • 工作流程:生產者將消息發送到交換機,交換機將消息廣播到綁定到它的所有隊列,每個綁定的隊列對應的消費者都能收到消息。
  • 應用場景:適用于一個消息需要被多個不同的服務或模塊接收和處理的場景,如系統的通知功能。

以下是發布/訂閱(Publish/Subscribe)模式的使用案例。

配置類定義

定義一個 FanoutExchange 類型的交換機與三個隊列,讓三個隊列綁定到該交換機。

FanoutExchange 交換機不需要指定 RoutingKey。因為 FanoutExchange 交換機會將消息統一發送給與其綁定的所有隊列,指定 RoutingKey 實際上沒有任何意義。

package test;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class PublishSubscribeConfig {@Beanpublic Queue publishSubscribeQueue1() {return new Queue("publish-subscribe-queue-1");}@Beanpublic Queue publishSubscribeQueue2() {return new Queue("publish-subscribe-queue-2");}@Beanpublic Queue publishSubscribeQueue3() {return new Queue("publish-subscribe-queue-3");}@Beanpublic FanoutExchange publishSubscribeFanoutExchange() {return new FanoutExchange("publish-subscribe-fanout-exchange");}@Beanpublic Binding publishSubscribeBinding1() {return BindingBuilder.bind(publishSubscribeQueue1()).to(publishSubscribeFanoutExchange());}@Beanpublic Binding publishSubscribeBinding2() {return BindingBuilder.bind(publishSubscribeQueue2()).to(publishSubscribeFanoutExchange());}@Beanpublic Binding publishSubscribeBinding3() {return BindingBuilder.bind(publishSubscribeQueue3()).to(publishSubscribeFanoutExchange());}}

消費者定義

定義三個消費者,分別監聽三個不同的隊列。

第一個消費者:

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class PublishSubscribeConsumer01 {@RabbitListener(queues = "publish-subscribe-queue-1")public void receive(String message) {log.info("PublishSubscribeConsumer 01 receive a Message:{}",message);}}

第二個消費者:

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class PublishSubscribeConsumer02 {@RabbitListener(queues = "publish-subscribe-queue-2")public void receive(String message) {log.info("PublishSubscribeConsumer 02 receive a message:{}",message);}}

第三個消費者:

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class PublishSubscribeConsumer03 {@RabbitListener(queues = "publish-subscribe-queue-3")public void receive(String message) {log.info("PublishSubscribeConsumer 03 receive a message:{}",message);}}

發送消息測試消費

publish-subscribe-fanout-exchange 發送一條消息。

package test;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);rabbitTemplate.convertAndSend("publish-subscribe-fanout-exchange","","hello world!");}}

控制臺輸出:

在這里插入圖片描述

路由(Routing)模式

  • 結構:同樣包含生產者、交換機和多個隊列,但交換機類型為直連交換機(Direct Exchange),隊列通過路由鍵(routing key)綁定到交換機。
  • 工作流程:生產者發送消息時指定路由鍵,交換機根據路由鍵將消息路由到與之綁定的隊列,只有綁定了對應路由鍵的隊列才能收到消息。
  • 應用場景:適用于根據不同的業務規則將消息路由到不同隊列的場景,如根據日志的級別(info、error 等)將日志消息路由到不同的隊列。

以下是路由(Routing)模式的使用案例。

配置類定義

定義一個 DirectExchange,因為 DirectExchange 可以通過 RoutingKey 精確匹配消息,當然也可以使用其他類型的交換機,如 ToppicExchange

定義三個不同名稱的隊列,其中兩個隊列綁定相同的 RoutingKey,而另外一個單獨綁定一個隊列。

package test;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RoutingConfig {@Beanpublic DirectExchange routingExchange() {return ExchangeBuilder.directExchange("routing-exchange").durable(true).build();}@Beanpublic Queue routingQueue1() {return QueueBuilder.durable("routing-queue-1").build();}@Beanpublic Queue routingQueue2() {return QueueBuilder.durable("routing-queue-2").build();}@Beanpublic Queue routingQueue3() {return QueueBuilder.durable("routing-queue-3").build();}@Beanpublic Binding routingQueue1ToRoutingExchangeBinding() {return BindingBuilder.bind(routingQueue1()).to(routingExchange()).with("routing-key-1");}@Beanpublic Binding routingQueue2ToRoutingExchangeBinding() {return BindingBuilder.bind(routingQueue2()).to(routingExchange()).with("routing-key-2");}@Beanpublic Binding routingQueue3ToRoutingExchangeBinding() {return BindingBuilder.bind(routingQueue3()).to(routingExchange()).with("routing-key-2");}}

消費者定義

定義三個消費者,分別監聽三個不同的隊列。

第一個消費者:

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class RoutingQueueConsumer01 {@RabbitListener(queues = "routing-queue-1")public void receive(String message){log.info("RoutingQueueConsumer01 receive a message:{}",message);}}

第二個消費者:

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class RoutingQueueConsumer02 {@RabbitListener(queues = "routing-queue-2")public void receive(String message){log.info("RoutingQueueConsumer02 receive a message:{}",message);}}

第三個消費者:

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class RoutingQueueConsumer03 {@RabbitListener(queues = "routing-queue-3")public void receive(String message){log.info("RoutingQueueConsumer03 receive a message:{}",message);}}

發送消費測試消費

向交換機發送消息,并指定 RoutingKey 為其中的兩個。

package test;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);rabbitTemplate.convertAndSend("routing-exchange", "routing-key-1", "hello world by routing-key-1!");rabbitTemplate.convertAndSend("routing-exchange", "routing-key-2", "hello world by routing-key-2!");}}

控制臺輸出:

在這里插入圖片描述

上述結果中,三個消費者都接受到了消息并成功處理。但實際上發送消息時,交換機只向兩個 RoutingKey 發送消息,而另外一個 RoutingKey 并沒有發送。這樣的情況下,三個消息者監聽三個不同隊列仍然能夠接受消息并處理,這是因為它們監聽的隊列所綁定的 RoutingKey 都被交換機投遞了消息。

主題(Topics)模式

  • 結構:包含生產者、主題交換機(Topic Exchange)和多個隊列,隊列通過綁定鍵(binding key)綁定到交換機,綁定鍵可以使用通配符。
  • 工作流程:生產者發送消息時指定路由鍵,交換機根據綁定鍵和路由鍵的匹配規則將消息路由到相應的隊列。
  • 應用場景:適用于需要根據消息的主題進行靈活路由的場景,如新聞分類訂閱,用戶可以根據不同的主題訂閱不同的新聞。

生產者發送包含主題的消息,主題由一個或多個單詞組成,單詞之間使用點號 . 進行分隔。消費者可以使用通配符 *# 對主題進行模糊匹配:

  • *:匹配一個單詞,可以代表任意一個詞。
  • #:匹配零個或多個單詞,可以代表一個或多個詞。

以下是主題(Topics)模式的使用案例。

配置類定義

定義一個 TopicExchange,分別通過 log.info.*log.error.#RoutingKey 綁定到兩個不同的隊列。

package test;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class TopicConfig {@Beanpublic Queue topicQueue1() {return new Queue("topic-queue-1");}@Beanpublic Queue topicQueue2() {return new Queue("topic-queue-2");}@Beanpublic TopicExchange topicExchange() {return new TopicExchange("topic-exchange");}@Beanpublic Binding bindingExchange() {return BindingBuilder.bind(topicQueue1()).to(topicExchange()).with("log.info.*");}@Beanpublic Binding bindingExchange2() {return BindingBuilder.bind(topicQueue2()).to(topicExchange()).with("log.error.#");}}

消費者定義

定義兩個消費者分別監聽兩個不同隊列。

第一個消費者:

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class TopicQueueConsumer01 {@RabbitListener(queues = "topic-queue-1")public void receive(String message){log.info("TopicQueueConsumer01 receive a message:{}",message);}}

第二個消費者:

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class TopicQueueConsumer02 {@RabbitListener(queues = "topic-queue-2")public void receive(String message){log.info("TopicQueueConsumer02 receive a message:{}",message);}}

發送消息測試消費

topic-exchange 交換機發送六條消息,通過不同的 RoutingKey

package test;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);rabbitTemplate.convertAndSend("topic-exchange", "log.info.base", "log.info.base message!");rabbitTemplate.convertAndSend("topic-exchange", "log.info.customer", "log.info.customer message!");rabbitTemplate.convertAndSend("topic-exchange", "log.info.shop.goods", "log.info.shop.goods message!");rabbitTemplate.convertAndSend("topic-exchange", "log.error.base", "log.error.base message!");rabbitTemplate.convertAndSend("topic-exchange", "log.error.customer", "log.error.customer message!");rabbitTemplate.convertAndSend("topic-exchange", "log.error.shop.goods", "log.error.shop.goods message!");}}

控制臺輸出:

在這里插入圖片描述

RPC(Remote Procedure Call)模式

  • 結構:包含客戶端(生產者)、服務端(消費者)、請求隊列和響應隊列。
  • 工作流程:客戶端發送請求消息到請求隊列,并設置一個回調隊列用于接收響應;服務端從請求隊列獲取請求消息,處理后將響應消息發送到回調隊列,客戶端從回調隊列獲取響應。
  • 應用場景:適用于需要在分布式系統中進行遠程過程調用的場景,如微服務之間的調用。

以下是主題(Topics)模式的使用案例。

配置類定義

定義一個交換機與一個隊列,通過隊列名進行綁定。

package test;import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RpcConfig {@Beanpublic Queue rpcQueue() {return new Queue("rpc-queue", true);}@Beanpublic DirectExchange rpcExchange() {return new DirectExchange("rpc-exchange");}@Beanpublic Binding rpcQueueToRpcExchangeBinding() {return BindingBuilder.bind(rpcQueue()).to(rpcExchange()).withQueueName();}@Beanpublic Jackson2JsonMessageConverter jackson2JsonMessageConverter() {return new Jackson2JsonMessageConverter();}}

請求與響應實體類

創建 RPC 請求與響應實體類。

package test;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class RpcRequest implements Serializable {private String message;}
package test;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class RpcResponse implements Serializable {private int result;}

消費者定義

定義一個消費者從隊列中接收消息。

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Service
@Slf4j
public class RpcServer {@RabbitListener(queues = "rpc-queue")public RpcResponse handleRpcRequest(RpcRequest request) {log.info("RPC接收的消息:{}", request);return new RpcResponse(0);}}

發送消息測試消費

測試 RPC 消息的發送。

package test;import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
@Slf4j
public class SpringBootApp {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(SpringBootApp.class, args);RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);String exchange = "rpc-exchange";String routingKey = "rpc-queue";RpcRequest rpcRequest = new RpcRequest("Rpc message!");RpcResponse rpcResponse = (RpcResponse) rabbitTemplate.convertSendAndReceive(exchange, routingKey, rpcRequest);log.info("RPC返回的結果:{}", rpcResponse);}}

控制臺輸出:

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79942.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79942.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79942.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

民宿管理系統6

普通管理員管理&#xff1a; 新增普通管理員&#xff1a; 前端效果&#xff1a; 前端代碼&#xff1a; <body> <div class"layui-fluid"><div class"layui-row"><div class"layui-form"><div class"layui-f…

vue3+ant design vue + Sortable實現多級表格列拖動

1、最近遇到個需求&#xff0c;需使用vue3ant design vue Sortable實現多級表格的表頭允許用戶拖拽移動。即當用戶拖拽一級表頭時&#xff0c;其對應的子級表頭及數據應同步移動&#xff0c;并且只允許一級非固定表頭允許拖拽。 2、代碼 <a-table:data-source"rowDat…

第五十四篇 AI與數據分析

一、AI數據分析就像做菜 想象你在廚房做一道新菜&#xff0c;AI數據分析的流程其實非常相似&#xff1a; 買菜&#xff08;獲取數據&#xff09; 去市場挑選新鮮蔬菜 從Excel/數據庫獲取數據例&#xff1a;pd.read_csv(超市銷售表.csv) 洗菜切菜&#xff08;清洗數據&#x…

差分OPA verilogaA 模型

做電路設計&#xff0c;需要提前用理想模型如VerilogA模型做驗證。這里分享一個由ahdlib庫里單端opamp改造而來的差分opamp。參考何樂年的《模擬集成電路設計與仿真》10.4節423頁&#xff1b; 描述的小信號模型如上。 VerilogA 用到了SRI/C&#xff0c;GBWgm/C,gaingm*r1等概念…

Solidity語言基礎:區塊鏈智能合約開發入門指南

一、Solidity概述 Solidity是以太坊生態系統中最重要的智能合約編程語言&#xff0c;由Gavin Wood于2014年提出。作為面向合約的高級語言&#xff0c;它結合了JavaScript、Python和C的語法特點&#xff0c;專為在以太坊虛擬機&#xff08;EVM&#xff09;上運行而設計。 核心…

開啟智能Kubernetes管理新時代:kubectl-ai讓操作更簡單!

在如今的科技世界中,Kubernetes 已經成為容器編排領域的標桿,幾乎所有現代應用的基礎設施都離不開它。然而,面對復雜的集群管理和日常運維,許多開發者常常感到無所適從。今天,我們將為大家介紹一款結合了人工智能的強大工具——kubectl-ai。它不僅能幫助開發者更加順暢地與…

2003-2020年高鐵站開通時間數據

2003-2020年高鐵站開通時間數據 1、時間&#xff1a;2003-2020年 2、來源&#xff1a;Chinese High-speed Rail and Airline Database&#xff0c;CRAD 3、指標&#xff1a;高鐵站名稱、開通時間、所在省份、所在城市、所屬線路名稱 4、說明&#xff1a; Hsrwsnm[高鐵站名…

神經網絡—感知器、多層感知器

文章目錄 前言一、生物神經元與感知器的類比二、感知器1、簡單感知器2、多層感知器&#xff08;1&#xff09;多層感知機結構 3、神經網絡結構 總結1、感知器的局限性如何突破感知器的局限性&#xff1f; 2、感知器的應用 前言 感知器&#xff08;Perceptron&#xff09;是神經…

避免數據丟失:在存儲測試數據之前,要做好Redis持久化

Redis提供兩種持久化方法&#xff1a; 一、RDB&#xff08;Redis DataBase&#xff09;&#xff1a; 1、周期性保存內存快照到磁盤&#xff08;生成 dump.rdb 文件&#xff09;。 2、配置save 相關參數。 我本地的配置如下&#xff1a; &#xff08;1&#xff09;配置文件re…

Oracle EBS FORM快捷鍵與觸發器的關系與使用

Oracle EBS FORM快捷鍵與觸發器的引用 1、快捷鍵作用&#xff0c;可以看文檔fmrweb.res 2、文件內容&#xff1a;標識了快捷鍵的作用 9 : 0 : “Tab” : 1 : “Next Field” 9 : 1 : “ShiftTab” : 2 : “Previous Field” 116 : 0 : “F5” : 3 : “Clear Field” 38 : 0 :…

Java 24:重構數字信任邊界 —— 后量子時代的智能安全防御體系構建

引言 在量子計算陰影與 AI 驅動攻擊交織的網絡安全新紀元&#xff0c;Java 平臺正經歷著自誕生以來最深刻的安全架構革新。作為企業級應用的核心基礎設施&#xff0c;Java 24 不僅延續了 “一次編寫&#xff0c;處處運行” 的跨平臺基因&#xff0c;更以后量子密碼學引擎、動態…

【故障定位系列】容器CPU問題引起的故障如何快速排查

原文地址&#xff1a;https://mp.weixin.qq.com/s/0VlIjbeEdPZUbLD389disA 當生產環境中的容器CPU出現異常時&#xff0c;可能會引發上層業務出現一系列問題&#xff0c;比如業務請求緩慢、網頁卡頓甚至崩潰等&#xff0c;如果沒有一個有效的故障定位方法&#xff0c;運維人員很…

DeepSeek 智能客服應用指南:構建、策略與成效升級

目錄 一、引言二、DeepSeek 與智能客服的相遇2.1 DeepSeek 的技術亮點2.2 智能客服&#xff1a;企業不可或缺的 “數字助手”2.3 DeepSeek 如何適配智能客服需求 三、基于 DeepSeek 搭建智能客服系統3.1 需求分析3.2 技術選型3.3 系統架構設計3.4 搭建步驟實操 四、基于 DeepSe…

JVM運行時數據區域(Run-Time Data Areas)的解析

# JVM運行時數據區域(Run-Time Data Areas)的解析 歡迎來到我的博客&#xff1a;TWind的博客 我的CSDN:&#xff1a;Thanwind-CSDN博客 我的掘金&#xff1a;Thanwinde 的個人主頁 本文參考于&#xff1a;深入理解Java虛擬機&#xff1a;JVM高級特性與最佳實踐 本文的JVM均…

【特別版】Kubernetes集群安裝(1master,2node)

Kubernetes集群安裝 虛擬機準備 按照三臺虛擬機標準&#xff0c;一臺控制節點兩臺工作節點 主機名ip配置要求master-k8s192.168.242.102GB或更多RAM&#xff0c;2個CPU或更多CPU&#xff0c;硬盤30GB或更多node01-k8s192.168.242.112GB或更多RAM&#xff0c;2個CPU或更多CPU…

Excel點擊單元格內容消失

Excel點擊單元格內容消失 前言一、原因說明二、解決方案1.菜單欄中找到“審閱”&#xff0c;選擇“撤銷工作表保護”2.輸入密碼3.解除成功 前言 Excel想要編輯單元格內容時&#xff0c;無論是單擊還是雙擊單元格內容都莫名其妙的消失了 一、原因說明 單擊或者雙擊Excel中單元…

最優化方法Python計算:有約束優化應用——線性Lasso回歸預測器

實際應用中&#xff0c;特征維度 n n n通常遠大于樣本容量 m m m&#xff08; n ? m n\ll m n?m&#xff09;&#xff0c;這種高維小樣本場景下特征數據可能含有對標簽數據 y i y_i yi?的取值不必要的成分&#xff0c;甚至是噪聲。此時&#xff0c;我們希望回歸模型中的優化…

如何為APP應用程序選擇合適的服務器

搭建一個成功的APP應用程序&#xff0c;服務器選擇是至關重要的決策之一。合適的服務器不僅能確保應用流暢運行&#xff0c;還能節省成本并保障安全性。本文將為您詳細解析如何為APP選擇最佳服務器方案。 一、了解您的APP需求 在選擇服務器前&#xff0c;首先需要明確您的應用…

k8s(11) — 探針和鉤子

鉤子和探針的區別&#xff1a; 在 Kubernetes&#xff08;k8s&#xff09;中&#xff0c;鉤子&#xff08;Hooks&#xff09;和探針&#xff08;Probes&#xff09;是保障應用穩定運行的重要機制&#xff0c;不過它們的用途和工作方式存在差異&#xff0c;以下為你詳細介紹&…

Kafka消息隊列之 【消費者分組】 詳解

消費者分組(Consumer Group)是 Kafka 提供的一種強大的消息消費機制,它允許多個消費者協同工作,共同消費一個或多個主題的消息,從而實現高吞吐量、可擴展性和容錯性。 基本概念 消費者分組:一組消費者實例的集合,這些消費者實例共同訂閱一個或多個主題,并通過分組來協調…