ActiveMQ-04如何搭建一个完美的ActiveMQ集群

集群架构是一个很大的话题,官网就给我们介绍了几种

  • 客户端:队列消费者集群-Queue Consumer Clusters
  • 服务端:Broker集群 - Broker Clusters
    • 静态发现
    • 动态发现
  • 服务端:Master-Slave 主从集群
    • Shared File System Master Slave
    • JDBC Master Slave
    • Replicated LevelDB Store(no longer supported)
  • Broker-Cluster+Master Slave的组合

在这里插入图片描述

客户端:队列消费者集群-Queue Consumer Clusters

竞争消费者模式,https://www.enterpriseintegrationpatterns.com/patterns/messaging/CompetingConsumers.html

对于点对点的队列模式(不是发布订阅模式),针对无状态的消息,多个消费者可以扩大消费者的处理能力。

对于有状态的消息而言,从ActiveMQ生产者的角度,发出的消息是能够遵循顺序的,单一的消费者就是顺序消费,如果是多个消费者并发消费,那么顺序就将被破坏。

从ActiveMQ解决方案看

  • 第一就是控制同一时间只有一个消费者来保证消费的顺序
  • 第二是通过消息组来保证组内消费是顺序的,组间依旧是负载均衡

服务端:Broker集群 - Broker Clusters

JMS 上下文中最常见的集群模型就是一组 JMS broker,客户端去连接去中一个,只要有一个无法提供服务了,就自动连到其他节点。

因此ActiveMQ就提供了failover://的客户端连接方式。客户端配置使用静态发现(写死地址配置)或动态发现(支持自动配置), 一旦一个broker无法服务就会自动连接到另一个。

这个动作仅仅在客户端侧,但是如果多个broker是不相通没有联系的,那么消息生产者依旧投递,异常的broker上数据仍然会堆积。目前解决方案就是创建一个网络来存储和转发这些消息,避免消息再发到异常的broker上。

客户端配置使用静态发现或动态发现是依托Broker之间的网络,来支持自动的故障转移和发现

静态发现和动态发现就是两种配置模式,差异不大。

Broker-Cluster的模式在实际生产应用中其实也是一个不错的选择,靠节点之间协同消费,来提升整体的性能,但是如果某个节点挂机,并且数据已经被持久化到对应的节点后,可能会导致部分数据堆积在故障节点上

静态发现

配置固定可连接的地址,是生产中常用的配置方式

<networkConnectors><networkConnector uri="static:(tcp://other-broker:port)" duplex="false"/>
</networkConnectors>

比如:

<!--amq1.acitvemq.xml中--><networkConnectors><networkConnector uri="static:(tcp://amq1:61616)" duplex="false"/></networkConnectors><!--amq2.acitvemq.xml中--><networkConnectors><networkConnector uri="static:(tcp://amq2:61616)" duplex="false"/></networkConnectors>

互为备份,我中有你,你中有我。

多个节点还可以是

<!--amq1.acitvemq.xml中-->
<networkConnectors></networkConnectors><!--amq2.acitvemq.xml中-->
<networkConnectors><networkConnector uri="static:(tcp://amq1:61616)" duplex="true"/>
</networkConnectors><!--amq3.acitvemq.xml中-->
<networkConnectors><networkConnector uri="static:(tcp://amq1:61616,tcp://amq2:61618)" duplex="true"/>
</networkConnectors>

<transportConnectors>节点都是正常配置即可。

关于duplex的配置,这个参数是全双工的含义,代表双端可以同时进行双向传输,就如平时的在电话中通话那样。如果非全双工的,那么你连我或者我连你,类似计算机和打印机之间的通信是单工模式,只有计算机向打印机传输数据,而没有相反
方向的数据传输。

  • 如果 duplex=true 那在brokerA配置,即可双端确认连接,brokerB就不需要再配置了
  • 如果 duplex=false 这是默认的情况,两边 activemq.xml 文件下都需要配置,以确保两边可通信

动态发现

通过组播的形式,获取可连接地址,需要调整 <transportConnectors><networkConnectors> 两个地方

<broker name="foo"><transportConnectors><transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600" discoveryUri="multicast://default"/></transportConnectors>...<networkConnectors><networkConnector uri="multicast://default"/>
</networkConnectors>
</broker>

着重就是在 uridiscoveryUri 的配置上。

在这里插入图片描述

服务端:Master-Slave 主从集群

主从集群有分为两种:

  • 一种是通过共享文件实现主从集群,一般通过共享挂载目录或存储实现,默认是KahaDB。主要通过多个节点同时抢占文件锁,但仅有一个节点可以获取文件锁的形式,从而保证只有一个主其他多个从待命。
  • 一种是通过JDBC数据库存储的方式实现共享的主从集群,配置会稍微繁琐些,并且服务的性能受数据库性能影响。主要通过多个节点同时抢占数据库锁资源,但仅有一个节点可以获取锁,从而保证只有一个主其他从待命。

Shared File System Master Slave

通过共享的文件系统,实现主从集群,主节点通过故障转移自动恢复查询新的主节点。

共享的文件系统是通过底层的文件锁实现的,首先要确保能够有文件锁。

使用 docker-compose 配置后,启动服务能够发现,多个节点会同时启动,但是最终仅有一个节点能够拿到锁,并正常启动完整服务,对外提供服务。

amq1    |  INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]
amq1    |  INFO | Starting Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]
amq1    |  INFO | Database /opt/apache-activemq/data/kahadb/lock is locked by another server. This broker is now in slave mode waiting a lock to be acquired
amq2    |  INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]
amq2    |  INFO | Starting Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]
amq2    |  INFO | Database /opt/apache-activemq/data/kahadb/lock is locked by another server. This broker is now in slave mode waiting a lock to be acquired
amq3    |  INFO | Starting Temp Data Store
amq3    |  INFO | PListStore:[/opt/apache-activemq/data/sharedfilesystem_mastersalve/tmp_storage] started
amq3    |  INFO | Starting Job Scheduler Store
amq3    |  INFO | Persistence Adapter successfully started
amq3    |  INFO | Apache ActiveMQ 6.0.1 (sharedfilesystem_mastersalve, ID:amq3-32923-1710911682404-0:1) is starting
amq3    |  INFO | Listening for connections at: tcp://amq3:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq3    |  INFO | Connector openwire started
amq3    |  INFO | Listening for connections at: amqp://amq3:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq3    |  INFO | Connector amqp started
amq3    |  INFO | Listening for connections at: stomp://amq3:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq3    |  INFO | Connector stomp started
amq3    |  INFO | Listening for connections at: mqtt://amq3:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq3    |  INFO | Connector mqtt started
amq3    |  INFO | Starting Jetty server
amq3    |  INFO | Creating Jetty connector
amq3    |  WARN | ServletContext@o.e.j.s.ServletContextHandler@51d719bc{/,null,STARTING} has uncovered HTTP methods for the following paths: [/]
amq3    |  INFO | Listening for connections at ws://amq3:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq3    |  INFO | Connector ws started
amq3    |  INFO | Apache ActiveMQ 6.0.1 (sharedfilesystem_mastersalve, ID:amq3-32923-1710911682404-0:1) started
amq3    |  INFO | For help or more information please see: http://activemq.apache.org
amq3    |  WARN | Store limit is 102400 mb (current store usage is 0 mb). The data directory: /opt/apache-activemq/data/kahadb only has 16756 mb of usable space. - resetting to maximum available disk space: 16756 mb
amq3    |  WARN | Temporary Store limit is 51200 mb (current store usage is 0 mb). The data directory: /opt/apache-activemq/data only has 20887 mb of usable space. - resetting to maximum available disk space: 20887 mb
amq3    |  INFO | ActiveMQ WebConsole available at http://0.0.0.0:8161/
amq3    |  INFO | ActiveMQ Jolokia REST API available at http://0.0.0.0:8161/api/jolokia/

注意这句话:lock is locked by another server. This broker is now in slave mode waiting a lock to be acquired, 即表示该节点未拿到锁,成为从节点待命。

主节点的 web 页面启动并提供服务,从节点的无法访问。

如果我们主动暂停主节点 amq3, 我们从日志上能够看到从节点自动去争抢锁,最终一个从节点晋升为主节点。

amq3 exited with code 137
amq1    |  INFO | Starting KahaDBStore
amq1    |  INFO | Opening MessageDatabase
amq1    |  INFO | Page File: /opt/apache-activemq/data/kahadb/db.data. Recovering pageFile free list due to prior unclean shutdown..
amq1    |  INFO | KahaDB is version 7
amq1    |  INFO | Page File: /opt/apache-activemq/data/kahadb/db.data. Recovered pageFile free list of size: 0
amq1    |  INFO | Starting Temp Data Store
amq1    |  INFO | PListStore:[/opt/apache-activemq/data/sharedfilesystem_mastersalve/tmp_storage] started
amq1    |  INFO | Starting Job Scheduler Store
amq1    |  INFO | Persistence Adapter successfully started
amq1    |  INFO | Apache ActiveMQ 6.0.1 (sharedfilesystem_mastersalve, ID:amq1-37999-1710912442351-0:1) is starting
amq1    |  INFO | Listening for connections at: tcp://amq1:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq1    |  INFO | Connector openwire started
amq1    |  INFO | Listening for connections at: amqp://amq1:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq1    |  INFO | Connector amqp started
amq1    |  INFO | Listening for connections at: stomp://amq1:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq1    |  INFO | Connector stomp started
amq1    |  INFO | Listening for connections at: mqtt://amq1:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq1    |  INFO | Connector mqtt started
amq1    |  INFO | Starting Jetty server
amq1    |  INFO | Creating Jetty connector
amq1    |  WARN | ServletContext@o.e.j.s.ServletContextHandler@1fc713c9{/,null,STARTING} has uncovered HTTP methods for the following paths: [/]
amq1    |  INFO | Listening for connections at ws://amq1:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq1    |  INFO | Connector ws started
amq1    |  INFO | Apache ActiveMQ 6.0.1 (sharedfilesystem_mastersalve, ID:amq1-37999-1710912442351-0:1) started
amq1    |  INFO | For help or more information please see: http://activemq.apache.org
amq1    |  WARN | Store limit is 102400 mb (current store usage is 0 mb). The data directory: /opt/apache-activemq/data/kahadb only has 14929 mb of usable space. - resetting to maximum available disk space: 14929 mb
amq1    |  WARN | Temporary Store limit is 51200 mb (current store usage is 0 mb). The data directory: /opt/apache-activemq/data only has 20886 mb of usable space. - resetting to maximum available disk space: 20886 mb
amq1    |  INFO | ActiveMQ WebConsole available at http://0.0.0.0:8161/
amq1    |  INFO | ActiveMQ Jolokia REST API available at http://0.0.0.0:8161/api/jolokia/

此时,amq1 已经成为主节点,如果 amq3 这时恢复了服务并启动,那么依旧成为从节点。

JDBC Master Slave

基于数据库的,主要就是通过链接数据库,依靠数据库的属性实现,提供4种配置样例:MySQL\PostgreSQL\Oracle\Derby。

<beans><!-- Allows us to use system properties as variables in this configuration file --><bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/><broker xmlns="http://activemq.apache.org/schema/core"><destinationPolicy><policyMap><policyEntries><policyEntry topic="FOO.>"><dispatchPolicy><strictOrderDispatchPolicy /></dispatchPolicy><subscriptionRecoveryPolicy><lastImageSubscriptionRecoveryPolicy /></subscriptionRecoveryPolicy></policyEntry></policyEntries></policyMap></destinationPolicy><persistenceAdapter><jdbcPersistenceAdapter dataDirectory="${activemq.base}/activemq-data"/><!-- <jdbcPersistenceAdapter dataDirectory="activemq-data" dataSource="#oracle-ds"/>--> </persistenceAdapter><transportConnectors><transportConnector name="default" uri="tcp://localhost:61616"/></transportConnectors></broker><!--  This xbean configuration file supports all the standard spring xml configuration options --><!-- Postgres DataSource Sample Setup --><!-- <bean id="postgres-ds" class="org.postgresql.ds.PGPoolingDataSource"><property name="serverName" value="localhost"/><property name="databaseName" value="activemq"/><property name="portNumber" value="0"/><property name="user" value="activemq"/><property name="password" value="activemq"/><property name="dataSourceName" value="postgres"/><property name="initialConnections" value="1"/><property name="maxConnections" value="10"/></bean>--><!-- MySql DataSource Sample Setup --><!-- <bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost/activemq?relaxAutoCommit=true"/><property name="username" value="activemq"/><property name="password" value="activemq"/><property name="poolPreparedStatements" value="true"/></bean>-->  <!-- Oracle DataSource Sample Setup --><!--<bean id="oracle-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"><property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/><property name="url" value="jdbc:oracle:thin:@localhost:1521:AMQDB"/><property name="username" value="scott"/><property name="password" value="tiger"/><property name="poolPreparedStatements" value="true"/></bean>--><!-- Embedded Derby DataSource Sample Setup --><!-- <bean id="derby-ds" class="org.apache.derby.jdbc.EmbeddedDataSource"><property name="databaseName" value="derbydb"/><property name="createDatabase" value="create"/></bean>-->  </beans>

Replicated LevelDB Store(no longer supported)

Replicated LevelDB 存储是依靠 ZooKeeper 的路径特性,来选取一个唯一值的做主节点,并且对ZooKeeper的依赖性还比较大。

它的出现是一种新的灵活的主从的方法,但是在历史的演进中,ActiveMQ开发了KahaDB来优化自己的效率,LevelDB又没有与时俱进地对ActiveMQ的版本进行兼容,导致部分版本中使用可能出现性能问题。

从ActiveMQ的角度,因为它可能存在的不稳定性而逐步不推荐或不支持,从使用者的角度,由于它可能存在的不稳定因素而逐步成为非选择项。使用的人越少,越没人维护。

当然在一些版本中,这也视为是一种解决方案,想要配置的话,可以参考官方的指导。

Broker-Cluster+Master Slave的组合

  • 对于 Broker-Cluster,如果某个节点一旦挂机,已被拉取的数据就会存在挂机的节点上无法被消费
  • 对于 Master-Slave,多个节点只能有一个主节点,从节点主要做灾备,并不能很好地扩展性能

对于以上两种模式的局限性,可用性和性能无法兼备,想两者兼备就可以将两种模式叠加

  • 组装两个 shared-file-system的master-slave集群
  • 配置两个集群间,是broker-cluster的关系

以下给出配置的样例:

docker-compose.yaml:

version: '3.8'
services: amq1:image: apache/activemq-classic:latestcontainer_name: amq1hostname: amq1volumes:- ./amq1/conf/activemq.xml:/opt/apache-activemq/conf/activemq.xml- ./amq1/conf/jetty.xml:/opt/apache-activemq/conf/jetty.xml- ./data1/kahadb:/opt/apache-activemq/data/kahadbports:- "61616:61616"- "8161:8161"     environment:ACTIVEMQ_BROKER_NAME: ms-broker-anetworks:- amqcluster    amq2:image: apache/activemq-classic:latestcontainer_name: amq2hostname: amq2volumes:- ./amq2/conf/activemq.xml:/opt/apache-activemq/conf/activemq.xml- ./amq2/conf/jetty.xml:/opt/apache-activemq/conf/jetty.xml- ./data1/kahadb:/opt/apache-activemq/data/kahadb     ports:- "61617:61616" - "8162:8161"  environment:ACTIVEMQ_BROKER_NAME: ms-broker-adepends_on:- amq1  networks:- amqcluster amq3:image: apache/activemq-classic:latestcontainer_name: amq3hostname: amq3volumes:- ./amq3/conf/activemq.xml:/opt/apache-activemq/conf/activemq.xml- ./amq3/conf/jetty.xml:/opt/apache-activemq/conf/jetty.xml- ./data2/kahadb:/opt/apache-activemq/data/kahadb      ports:- "61618:61616" - "8163:8161"     environment:ACTIVEMQ_BROKER_NAME: ms-broker-bnetworks:- amqcluster                 amq4:image: apache/activemq-classic:latestcontainer_name: amq4hostname: amq4volumes:- ./amq4/conf/activemq.xml:/opt/apache-activemq/conf/activemq.xml- ./amq4/conf/jetty.xml:/opt/apache-activemq/conf/jetty.xml- ./data2/kahadb:/opt/apache-activemq/data/kahadb      ports:- "61619:61616" - "8164:8161"       environment:ACTIVEMQ_BROKER_NAME: ms-broker-bdepends_on:- amq3    networks:- amqcluster                       
networks:amqcluster:external: true

activemq.xml 的配置

<!--amq1.activemq.xml--><networkConnectors><networkConnector uri="masterslave:(tcp://amq1:61616,tcp://amq2:61616)" duplex="false" /><networkConnector name="ms-broker-b" uri="static:(tcp://amq3:61616,tcp://amq4:61616)" duplex="true" /></networkConnectors><persistenceAdapter><kahaDB directory="${activemq.data}/kahadb"/></persistenceAdapter><!--amq2.activemq.xml--><networkConnectors><networkConnector uri="masterslave:(tcp://amq1:61616,tcp://amq2:61616)" duplex="false" /><networkConnector name="ms-broker-b" uri="static:(tcp://amq3:61616,tcp://amq4:61616)" duplex="true" /></networkConnectors><persistenceAdapter><kahaDB directory="${activemq.data}/kahadb"/></persistenceAdapter>   <!--amq3.activemq.xml--><networkConnectors><networkConnector uri="masterslave:(tcp://amq3:61616,tcp://amq4:61616)" duplex="false" /></networkConnectors>    <persistenceAdapter><kahaDB directory="${activemq.data}/kahadb"/></persistenceAdapter><!--amq4.activemq.xml--><networkConnectors><networkConnector uri="masterslave:(tcp://amq3:61616,tcp://amq4:61616)" duplex="false" /></networkConnectors>    <persistenceAdapter><kahaDB directory="${activemq.data}/kahadb"/></persistenceAdapter>

其中 duplex 配置 true/false 可自选,但是配置方式稍有不同,具体参看 服务端:Broker集群 - Broker Clusters 这边的描述

最终启动另个集群,一切是符合预期的,amq1\amq3ms-broker-a\ms-broker-b 的两个集群的主节点,amq2\amq4 是两个从节点,两个主节点提供服务,两个从节点不接受其他外部链接

Creating amq3 ... doneCreating amq1 ... doneCreating amq4 ... doneCreating amq2 ... doneAttaching to amq3, amq1, amq2, amq4amq1    | INFO: Loading '/opt/apache-activemq/bin/setenv'amq2    | INFO: Loading '/opt/apache-activemq/bin/setenv'amq1    | INFO: Using java '/opt/java/openjdk/bin/java'amq3    | INFO: Loading '/opt/apache-activemq/bin/setenv'amq2    | INFO: Using java '/opt/java/openjdk/bin/java'amq1    | INFO: Starting in foreground, this is just for debugging purposes (stop process by pressing CTRL+C)amq1    | INFO: Creating pidfile /opt/apache-activemq/data/activemq.pidamq3    | INFO: Using java '/opt/java/openjdk/bin/java'amq4    | INFO: Loading '/opt/apache-activemq/bin/setenv'amq2    | INFO: Starting in foreground, this is just for debugging purposes (stop process by pressing CTRL+C)amq2    | INFO: Creating pidfile /opt/apache-activemq/data/activemq.pidamq1    | Java Runtime: Eclipse Adoptium 17.0.9 /opt/java/openjdkamq1    |   Heap sizes: current=65536k  free=59544k  max=1007616kamq1    |     JVM args: -Djetty.host=0.0.0.0 -Dcom.sun.management.jmxremote -Djava.awt.headless=true -Djava.io.tmpdir=/opt/apache-activemq/tmp --add-reads=java.xml=java.logging --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.naming/javax.naming.spi=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.http=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.https=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.jar=ALL-UNNAMED --add-exports=jdk.xml.dom/org.w3c.dom.html=ALL-UNNAMED --add-exports=jdk.naming.rmi/com.sun.jndi.url.rmi=ALL-UNNAMED -Dactivemq.classpath=/opt/apache-activemq/conf:/opt/apache-activemq/../lib/: -Dactivemq.home=/opt/apache-activemq -Dactivemq.base=/opt/apache-activemq -Dactivemq.conf=/opt/apache-activemq/conf -Dactivemq.data=/opt/apache-activemq/data -Djolokia.conf=file:/opt/apache-activemq/conf/jolokia-access.xmlamq1    | Extensions classpath:amq1    |   [/opt/apache-activemq/lib,/opt/apache-activemq/lib/camel,/opt/apache-activemq/lib/optional,/opt/apache-activemq/lib/web,/opt/apache-activemq/lib/extra]amq3    | INFO: Starting in foreground, this is just for debugging purposes (stop process by pressing CTRL+C)amq4    | INFO: Using java '/opt/java/openjdk/bin/java'amq3    | INFO: Creating pidfile /opt/apache-activemq/data/activemq.pidamq1    | ACTIVEMQ_HOME: /opt/apache-activemqamq1    | ACTIVEMQ_BASE: /opt/apache-activemqamq1    | ACTIVEMQ_CONF: /opt/apache-activemq/confamq1    | ACTIVEMQ_DATA: /opt/apache-activemq/dataamq3    | Java Runtime: Eclipse Adoptium 17.0.9 /opt/java/openjdkamq3    |   Heap sizes: current=65536k  free=59544k  max=1007616kamq3    |     JVM args: -Djetty.host=0.0.0.0 -Dcom.sun.management.jmxremote -Djava.awt.headless=true -Djava.io.tmpdir=/opt/apache-activemq/tmp --add-reads=java.xml=java.logging --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.naming/javax.naming.spi=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.http=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.https=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.jar=ALL-UNNAMED --add-exports=jdk.xml.dom/org.w3c.dom.html=ALL-UNNAMED --add-exports=jdk.naming.rmi/com.sun.jndi.url.rmi=ALL-UNNAMED -Dactivemq.classpath=/opt/apache-activemq/conf:/opt/apache-activemq/../lib/: -Dactivemq.home=/opt/apache-activemq -Dactivemq.base=/opt/apache-activemq -Dactivemq.conf=/opt/apache-activemq/conf -Dactivemq.data=/opt/apache-activemq/data -Djolokia.conf=file:/opt/apache-activemq/conf/jolokia-access.xmlamq3    | Extensions classpath:amq3    |   [/opt/apache-activemq/lib,/opt/apache-activemq/lib/camel,/opt/apache-activemq/lib/optional,/opt/apache-activemq/lib/web,/opt/apache-activemq/lib/extra]amq3    | ACTIVEMQ_HOME: /opt/apache-activemqamq3    | ACTIVEMQ_BASE: /opt/apache-activemqamq3    | ACTIVEMQ_CONF: /opt/apache-activemq/confamq3    | ACTIVEMQ_DATA: /opt/apache-activemq/dataamq4    | INFO: Starting in foreground, this is just for debugging purposes (stop process by pressing CTRL+C)amq4    | INFO: Creating pidfile /opt/apache-activemq/data/activemq.pidamq2    | Java Runtime: Eclipse Adoptium 17.0.9 /opt/java/openjdkamq2    |   Heap sizes: current=65536k  free=59754k  max=1007616kamq2    |     JVM args: -Djetty.host=0.0.0.0 -Dcom.sun.management.jmxremote -Djava.awt.headless=true -Djava.io.tmpdir=/opt/apache-activemq/tmp --add-reads=java.xml=java.logging --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.naming/javax.naming.spi=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.http=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.https=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.jar=ALL-UNNAMED --add-exports=jdk.xml.dom/org.w3c.dom.html=ALL-UNNAMED --add-exports=jdk.naming.rmi/com.sun.jndi.url.rmi=ALL-UNNAMED -Dactivemq.classpath=/opt/apache-activemq/conf:/opt/apache-activemq/../lib/: -Dactivemq.home=/opt/apache-activemq -Dactivemq.base=/opt/apache-activemq -Dactivemq.conf=/opt/apache-activemq/conf -Dactivemq.data=/opt/apache-activemq/data -Djolokia.conf=file:/opt/apache-activemq/conf/jolokia-access.xmlamq2    | Extensions classpath:amq2    |   [/opt/apache-activemq/lib,/opt/apache-activemq/lib/camel,/opt/apache-activemq/lib/optional,/opt/apache-activemq/lib/web,/opt/apache-activemq/lib/extra]amq2    | ACTIVEMQ_HOME: /opt/apache-activemqamq2    | ACTIVEMQ_BASE: /opt/apache-activemqamq2    | ACTIVEMQ_CONF: /opt/apache-activemq/confamq2    | ACTIVEMQ_DATA: /opt/apache-activemq/dataamq4    | Java Runtime: Eclipse Adoptium 17.0.9 /opt/java/openjdkamq4    |   Heap sizes: current=65536k  free=59544k  max=1007616kamq4    |     JVM args: -Djetty.host=0.0.0.0 -Dcom.sun.management.jmxremote -Djava.awt.headless=true -Djava.io.tmpdir=/opt/apache-activemq/tmp --add-reads=java.xml=java.logging --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.naming/javax.naming.spi=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.http=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.https=ALL-UNNAMED --add-exports=java.base/sun.net.www.protocol.jar=ALL-UNNAMED --add-exports=jdk.xml.dom/org.w3c.dom.html=ALL-UNNAMED --add-exports=jdk.naming.rmi/com.sun.jndi.url.rmi=ALL-UNNAMED -Dactivemq.classpath=/opt/apache-activemq/conf:/opt/apache-activemq/../lib/: -Dactivemq.home=/opt/apache-activemq -Dactivemq.base=/opt/apache-activemq -Dactivemq.conf=/opt/apache-activemq/conf -Dactivemq.data=/opt/apache-activemq/data -Djolokia.conf=file:/opt/apache-activemq/conf/jolokia-access.xmlamq4    | Extensions classpath:amq4    |   [/opt/apache-activemq/lib,/opt/apache-activemq/lib/camel,/opt/apache-activemq/lib/optional,/opt/apache-activemq/lib/web,/opt/apache-activemq/lib/extra]amq4    | ACTIVEMQ_HOME: /opt/apache-activemqamq4    | ACTIVEMQ_BASE: /opt/apache-activemqamq4    | ACTIVEMQ_CONF: /opt/apache-activemq/confamq4    | ACTIVEMQ_DATA: /opt/apache-activemq/dataamq3    | Loading message broker from: xbean:activemq.xmlamq1    | Loading message broker from: xbean:activemq.xmlamq2    | Loading message broker from: xbean:activemq.xmlamq4    | Loading message broker from: xbean:activemq.xmlamq3    |  INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]amq3    |  INFO | Starting Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]amq3    |  INFO | Starting KahaDBStoreamq3    |  INFO | Opening MessageDatabaseamq3    |  INFO | Page File: /opt/apache-activemq/data/kahadb/db.data. Recovering pageFile free list due to prior unclean shutdown..amq1    |  INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]amq3    |  INFO | Page File: /opt/apache-activemq/data/kahadb/db.data. Recovered pageFile free list of size: 0amq3    |  INFO | KahaDB is version 7amq1    |  INFO | Starting Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]amq1    |  INFO | Starting KahaDBStoreamq1    |  INFO | Opening MessageDatabaseamq1    |  INFO | Page File: /opt/apache-activemq/data/kahadb/db.data. Recovering pageFile free list due to prior unclean shutdown..amq1    |  INFO | KahaDB is version 7amq1    |  INFO | Page File: /opt/apache-activemq/data/kahadb/db.data. Recovered pageFile free list of size: 0amq3    |  INFO | Starting Temp Data Storeamq3    |  INFO | PListStore:[/opt/apache-activemq/data/ms-broker-b/tmp_storage] startedamq3    |  INFO | Starting Job Scheduler Storeamq3    |  INFO | Persistence Adapter successfully startedamq1    |  INFO | Starting Temp Data Storeamq1    |  INFO | PListStore:[/opt/apache-activemq/data/ms-broker-a/tmp_storage] startedamq1    |  INFO | Starting Job Scheduler Storeamq1    |  INFO | Persistence Adapter successfully startedamq3    |  INFO | Apache ActiveMQ 6.0.1 (ms-broker-b, ID:amq3-37457-1711357687281-0:1) is startingamq1    |  INFO | Apache ActiveMQ 6.0.1 (ms-broker-a, ID:amq1-45023-1711357687416-0:1) is startingamq3    |  INFO | Listening for connections at: tcp://amq3:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600amq3    |  INFO | Connector openwire startedamq3    |  INFO | Listening for connections at: amqp://amq3:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600amq3    |  INFO | Connector amqp startedamq3    |  INFO | Listening for connections at: stomp://amq3:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600amq3    |  INFO | Connector stomp startedamq3    |  INFO | Listening for connections at: mqtt://amq3:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600amq3    |  INFO | Connector mqtt startedamq1    |  INFO | Listening for connections at: tcp://amq1:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600amq3    |  INFO | Starting Jetty serveramq1    |  INFO | Connector openwire startedamq1    |  INFO | Listening for connections at: amqp://amq1:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600amq1    |  INFO | Connector amqp startedamq1    |  INFO | Listening for connections at: stomp://amq1:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600amq1    |  INFO | Connector stomp startedamq1    |  INFO | Listening for connections at: mqtt://amq1:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600amq1    |  INFO | Connector mqtt started
amq2    |  INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]amq1    |  INFO | Starting Jetty serveramq2    |  INFO | Starting Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]amq2    |  INFO | Database /opt/apache-activemq/data/kahadb/lock is locked by another server. This broker is now in slave mode waiting a lock to be acquiredamq4    |  INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]amq4    |  INFO | Starting Persistence Adapter: KahaDBPersistenceAdapter[/opt/apache-activemq/data/kahadb]amq4    |  INFO | Database /opt/apache-activemq/data/kahadb/lock is locked by another server. This broker is now in slave mode waiting a lock to be acquiredamq3    |  INFO | Creating Jetty connectoramq1    |  INFO | Creating Jetty connectoramq3    |  WARN | ServletContext@o.e.j.s.ServletContextHandler@765ffb14{/,null,STARTING} has uncovered HTTP methods for the following paths: [/]amq3    |  INFO | Listening for connections at ws://amq3:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600amq3    |  INFO | Connector ws startedamq3    |  INFO | Establishing network connection from vm://ms-broker-b to failover:(tcp://amq3:61616,tcp://amq4:61616)?randomize=false&maxReconnectAttempts=0amq3    |  INFO | Connector vm://ms-broker-b startedamq3    |  INFO | Network Connector DiscoveryNetworkConnector:NC:BrokerService[ms-broker-b] startedamq3    |  INFO | Apache ActiveMQ 6.0.1 (ms-broker-b, ID:amq3-37457-1711357687281-0:1) startedamq3    |  INFO | For help or more information please see: http://activemq.apache.orgamq3    |  WARN | Store limit is 102400 mb (current store usage is 0 mb). The data directory: /opt/apache-activemq/data/kahadb only has 16037 mb of usable space. - resetting to maximum available disk space: 16037 mbamq3    |  WARN | Temporary Store limit is 51200 mb (current store usage is 0 mb). The data directory: /opt/apache-activemq/data only has 20872 mb of usable space. - resetting to maximum available disk space: 20872 mbamq1    |  WARN | ServletContext@o.e.j.s.ServletContextHandler@18578491{/,null,STARTING} has uncovered HTTP methods for the following paths: [/]amq1    |  INFO | Listening for connections at ws://amq1:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600amq1    |  INFO | Connector ws startedamq1    |  INFO | Establishing network connection from vm://ms-broker-a to failover:(tcp://amq1:61616,tcp://amq2:61616)?randomize=false&maxReconnectAttempts=0amq3    |  INFO | Successfully connected to tcp://amq3:61616amq1    |  INFO | Connector vm://ms-broker-a startedamq3    |  INFO | ms-broker-b Shutting down NCamq1    |  INFO | Network Connector DiscoveryNetworkConnector:NC:BrokerService[ms-broker-a] startedamq1    |  INFO | Establishing network connection from vm://ms-broker-a to tcp://amq3:61616amq3    |  WARN | Transport (tcp://amq3:61616) failed, not attempting to automatically reconnectamq3    | java.io.IOException: Bridge stoppedamq3    | at org.apache.activemq.network.DemandForwardingBridgeSupport.stopFailoverTransport(DemandForwardingBridgeSupport.java:355) [activemq-broker-6.0.1.jar:6.0.1]amq3    | at org.apache.activemq.network.DemandForwardingBridgeSupport.stop(DemandForwardingBridgeSupport.java:331) [activemq-broker-6.0.1.jar:6.0.1]amq3    | at org.apache.activemq.network.DemandForwardingBridgeSupport.serviceLocalCommand(DemandForwardingBridgeSupport.java:1308) [activemq-broker-6.0.1.jar:6.0.1]amq3    | at org.apache.activemq.network.DemandForwardingBridgeSupport$2.onCommand(DemandForwardingBridgeSupport.java:222) [activemq-broker-6.0.1.jar:6.0.1]amq3    | at org.apache.activemq.transport.ResponseCorrelator.onCommand(ResponseCorrelator.java:116) [activemq-client-6.0.1.jar:6.0.1]amq3    | at org.apache.activemq.transport.MutexTransport.onCommand(MutexTransport.java:50) [activemq-client-6.0.1.jar:6.0.1]amq3    | at org.apache.activemq.transport.vm.VMTransport.stop(VMTransport.java:227) [activemq-broker-6.0.1.jar:6.0.1]amq3    | at org.apache.activemq.transport.TransportFilter.stop(TransportFilter.java:72) [activemq-client-6.0.1.jar:6.0.1]amq3    | at org.apache.activemq.transport.TransportFilter.stop(TransportFilter.java:72) [activemq-client-6.0.1.jar:6.0.1]amq3    | at org.apache.activemq.transport.ResponseCorrelator.stop(ResponseCorrelator.java:132) [activemq-client-6.0.1.jar:6.0.1]amq3    | at org.apache.activemq.broker.TransportConnection.doStop(TransportConnection.java:1202) [activemq-broker-6.0.1.jar:6.0.1]amq3    | at org.apache.activemq.broker.TransportConnection$4.run(TransportConnection.java:1168) [activemq-broker-6.0.1.jar:6.0.1]amq3    | at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:?]amq3    | at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:?]amq3    | at java.base/java.lang.Thread.run(Unknown Source) [?:?]amq3    |  INFO | ms-broker-b bridge to Unknown stoppedamq3    |  INFO | Connector vm://ms-broker-b stoppedamq1    |  INFO | Establishing network connection from vm://ms-broker-a to tcp://amq4:61616amq1    |  INFO | Successfully connected to tcp://amq1:61616amq1    |  INFO | Network connection between vm://ms-broker-a#2 and tcp://amq3/172.22.0.2:61616@47714 (ms-broker-b) has been established.amq3    |  INFO | Connector vm://ms-broker-b startedamq1    |  INFO | ms-broker-a Shutting down NCamq3    |  INFO | Started responder end of duplex bridge ms-broker-b@ID:amq1-45023-1711357687416-0:1amq1    |  INFO | ms-broker-a bridge to Unknown stoppedamq1    |  INFO | ms-broker-a Shutting down ms-broker-bamq1    |  INFO | ms-broker-a bridge to Unknown stoppedamq1    |  WARN | Could not start network bridge between: vm://ms-broker-a and: tcp://amq4:61616 due to: Connection refusedamq1    |  INFO | Network Connector DiscoveryNetworkConnector:ms-broker-b:BrokerService[ms-broker-a] startedamq1    |  INFO | Apache ActiveMQ 6.0.1 (ms-broker-a, ID:amq1-45023-1711357687416-0:1) startedamq1    |  INFO | For help or more information please see: http://activemq.apache.orgamq3    |  INFO | Network connection between vm://ms-broker-b#2 and tcp:///172.22.0.3:47714@61616 (ms-broker-a) has been established.amq1    |  WARN | Store limit is 102400 mb (current store usage is 0 mb). The data directory: /opt/apache-activemq/data/kahadb only has 16037 mb of usable space. - resetting to maximum available disk space: 16037 mbamq1    |  WARN | Temporary Store limit is 51200 mb (current store usage is 0 mb). The data directory: /opt/apache-activemq/data only has 20872 mb of usable space. - resetting to maximum available disk space: 20872 mbamq3    |  INFO | ActiveMQ WebConsole available at http://0.0.0.0:8161/amq3    |  INFO | ActiveMQ Jolokia REST API available at http://0.0.0.0:8161/api/jolokia/amq1    |  INFO | Establishing network connection from vm://ms-broker-a to tcp://amq4:61616

而后可能看到一些错误日志:

amq1    |  INFO | ms-broker-a Shutting down ms-broker-bamq1    |  INFO | ms-broker-a bridge to Unknown stoppedamq1    |  INFO | Error with pending local brokerInfo on: vm://ms-broker-a#10 (peer (vm://ms-broker-a#11) stopped.)amq1    |  WARN | Could not start network bridge between: vm://ms-broker-a and: tcp://amq4:61616 due to: Connection refusedamq1    |  INFO | ActiveMQ WebConsole available at http://0.0.0.0:8161/amq1    |  INFO | ActiveMQ Jolokia REST API available at http://0.0.0.0:8161/api/jolokia/amq1    |  INFO | Establishing network connection from vm://ms-broker-a to tcp://amq4:61616amq1    |  INFO | ms-broker-a Shutting down ms-broker-bamq1    |  INFO | ms-broker-a bridge to Unknown stoppedamq1    |  WARN | Could not start network bridge between: vm://ms-broker-a and: tcp://amq4:61616 due to: Connection refused

这个也是很好理解,amq4是从节点,不接收其他连接,拒绝连接是符合预期的。

模拟向amq1生产50条数据,amq1消费20条数据,amq3消费20条数据 --> 流程正常,符合预期

ms-broker-a中:

在这里插入图片描述

ms-broker-b中:

在这里插入图片描述

ms-broker-b相当于 ms-broker-a 的消费者,触发消费后会获取A中残余消息。

继续模拟amq1挂机,amq2接替为主,向amq2生产50条消息,amq2消费20条数据,amq3消费20条数据 --> 流程正常,符合预期

amq1 exited with code 137
amq2    |  INFO | Starting KahaDBStore
amq2    |  INFO | Opening MessageDatabase
amq2    |  INFO | Page File: /opt/apache-activemq/data/kahadb/db.data. Recovering pageFile free list due to prior unclean shutdown..
amq2    |  INFO | KahaDB is version 7
amq2    |  INFO | Page File: /opt/apache-activemq/data/kahadb/db.data. Recovered pageFile free list of size: 0
amq2    |  INFO | Starting Temp Data Store
amq2    |  INFO | PListStore:[/opt/apache-activemq/data/ms-broker-a/tmp_storage] started
amq2    |  INFO | Starting Job Scheduler Store
amq2    |  INFO | Persistence Adapter successfully started
amq2    |  INFO | Apache ActiveMQ 6.0.1 (ms-broker-a, ID:amq2-37987-1711359807532-0:1) is starting
amq2    |  INFO | Listening for connections at: tcp://amq2:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq2    |  INFO | Connector openwire started
amq2    |  INFO | Listening for connections at: amqp://amq2:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq2    |  INFO | Connector amqp started
amq2    |  INFO | Listening for connections at: stomp://amq2:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq2    |  INFO | Connector stomp started
amq2    |  INFO | Listening for connections at: mqtt://amq2:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq2    |  INFO | Connector mqtt started
amq2    |  INFO | Starting Jetty server
amq2    |  INFO | Creating Jetty connector
amq2    |  WARN | ServletContext@o.e.j.s.ServletContextHandler@c269425{/,null,STARTING} has uncovered HTTP methods for the following paths: [/]
amq2    |  INFO | Listening for connections at ws://amq2:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600
amq2    |  INFO | Connector ws started
amq2    |  INFO | Establishing network connection from vm://ms-broker-a to failover:(tcp://amq1:61616,tcp://amq2:61616)?randomize=false&maxReconnectAttempts=0
amq2    | ERROR | Failed to Lookup INetAddress for URI[tcp://amq1:61616] : java.net.UnknownHostException: amq1: Name or service not known
amq2    |  INFO | Connector vm://ms-broker-a started
amq2    |  INFO | Network Connector DiscoveryNetworkConnector:NC:BrokerService[ms-broker-a] started
amq2    |  INFO | Establishing network connection from vm://ms-broker-a to tcp://amq3:61616
amq2    |  INFO | Successfully connected to tcp://amq2:61616
amq2    |  INFO | Establishing network connection from vm://ms-broker-a to tcp://amq4:61616
amq2    |  INFO | ms-broker-a Shutting down NC
amq2    |  INFO | ms-broker-a Shutting down brokerB
amq2    |  INFO | ms-broker-a bridge to Unknown stopped
amq2    |  INFO | ms-broker-a bridge to Unknown stopped
amq2    |  WARN | Could not start network bridge between: vm://ms-broker-a and: tcp://amq4:61616 due to: Connection refused
amq2    |  INFO | Network Connector DiscoveryNetworkConnector:brokerB:BrokerService[ms-broker-a] started
amq2    |  INFO | Apache ActiveMQ 6.0.1 (ms-broker-a, ID:amq2-37987-1711359807532-0:1) started
amq2    |  INFO | For help or more information please see: http://activemq.apache.org
amq2    |  INFO | Network connection between vm://ms-broker-a#2 and tcp://amq3/172.22.0.2:61616@40856 (ms-broker-b) has been established.
amq2    |  WARN | Store limit is 102400 mb (current store usage is 0 mb). The data directory: /opt/apache-activemq/data/kahadb only has 14987 mb of usable space. - resetting to maximum available disk space: 14987 mb
amq3    |  INFO | Connector vm://ms-broker-b started
amq2    |  WARN | Temporary Store limit is 51200 mb (current store usage is 0 mb). The data directory: /opt/apache-activemq/data only has 20870 mb of usable space. - resetting to maximum available disk space: 20870 mb
amq3    |  INFO | Started responder end of duplex bridge brokerB@ID:amq2-37987-1711359807532-0:1
amq3    |  INFO | Network connection between vm://ms-broker-b#6 and tcp:///172.22.0.5:40856@61616 (ms-broker-a) has been established.
amq2    |  INFO | ActiveMQ WebConsole available at http://0.0.0.0:8161/
amq2    |  INFO | ActiveMQ Jolokia REST API available at http://0.0.0.0:8161/api/jolokia/

从日志可以看到,amq1终止了,amq2顶替上了,最后与amq3连接起来,消息依旧正常生产和消费。

amq2-webconsole

在这里插入图片描述

amq3-webconsole

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


如果喜欢我的文章的话,可以去GitHub上给一个免费的关注吗?

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

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

相关文章

力扣hot100:207. 课程表

这是一道拓扑排序问题&#xff0c;也可以使用DFS判断图中是否存在环。详情请见&#xff1a;官方的BFS算法请忽略&#xff0c;BFS将问题的实际意义给模糊了&#xff0c;不如用普通拓扑排序思想。 数据结构&#xff1a;图的拓扑排序与关键路径 拓扑排序&#xff1a; class Sol…

鸿蒙APP开发实战:【Api9】拍照、拍视频;选择图片、视频、文件工具类

鸿蒙开发过程中&#xff0c;经常会进行系统调用&#xff0c;拍照、拍视频、选择图库图片、选择图库视频、选择文件。今天就给大家分享一个工具类。 1. 话不多说&#xff0c;先展示样式 2.设计思路 根据官方提供的指南开发工具类&#xff0c;基础的拍照、拍视频、图库选照片、…

【软考】设计模式之状态模式

目录 1. 说明2. 应用场景3. 结构图4. 构成5. 优缺点5.1 优点5.2 缺点 6. java示例6.1 非状态模式6.1.1 问题分析6.1.2 接口类6.1.2 实现类6.1.3 客户端6.1.4 结果截图 6.2 状态模式6.2.1 抽象状态类6.2.2 状态类6.2.3 上下文类6.2.4 上下文类 1. 说明 1.允许一个对象在其内部状…

ArcGIS矢量裁剪矢量

一、利用相交工具 Arctoolbox工具一分析工具一叠加分析一相交

react native

简介 React Native 就是使用React和应用平台的原生功能来构建 Android 和 iOS 应用的开源框架。在 Android 和 iOS 开发中&#xff0c;一个视图是 UI 的基本组成部分&#xff0c;React 组件通过 JavaScript 来调用这些视图。可以构建自己的 Native Components(原生组件)&#…

C# wpf 嵌入hwnd窗口

WPF Hwnd窗口互操作系列 第一章 嵌入Hwnd窗口&#xff08;本章&#xff09; 第二章 嵌入WinForm控件 第三章 嵌入WPF控件 文章目录 WPF Hwnd窗口互操作系列前言一、如何实现1、继承HwndHost2、实现抽象方法3、xaml中使用HwndHost控件 二、具体实现1、Win32窗口2、HwndSource窗…

思腾合力出席文化和旅游虚拟现实应用推广交流活动并作主题演讲

3月21日&#xff0c;由文化和旅游部产业发展司主办&#xff0c;中国信息通信研究院、北京市石景山区文化和旅游局、中国动漫集团有限公司承办的“数字赋能文旅场景建设行动——文化和旅游虚拟现实应用推广交流活动”在北京首钢一高炉SoReal科幻乐园成功举办。 思腾合力CMO徐莉受…

【第028篇】用IDEA打开并运行Eclipse创建的项目

下图我使用的是2021版本的idea 一、 导入 首先&#xff0c;点击左上方【File】-【New】-【Project from Existing Sources】 在目录中选择自己要导入的eclipse动态项目&#xff1b; 3、这里选择【import project from external model】&#xff0c;再选择【eclipse】&#…

【jenkins+cmake+svn管理c++项目】Windows环境安装以及工具配置

一、目标和环境 目标&#xff1a;搭建一个jenkins环境&#xff0c;实现jenkins调用cmake和svn和VS编译c项目&#xff0c;并将生成的库上传svn。 环境&#xff1a;win10虚拟机&#xff08;练习流程用&#xff0c;正式用的话还是放到服务器&#xff09;&#xff0c;VS2017. 二、…

Flask python :logging日志功能使用

logging日志的使用 一、了解flask日志1.1、Loggers记录器1.2、Handlers 处理器1.3、Formatters 格式化器 二、使用日志2.1、官网上的一个简单的示例2.2、基本配置2.3、具体使用示例2.4、运行 三、写在最后 一、了解flask日志 日志是一种非常重要的工具&#xff0c;可以帮助开发…

pandas 函数

pandas是基于numpy数组构建的&#xff0c;但二者最大的不同是pandas是专门为处理表格和混杂数据设计的&#xff0c;比较契合统计分析中的表结构&#xff0c;而numpy更适合处理统一的数值数组数据。pandas数组结构有一维Series和二维DataFrame。 Series的字符串表现形式为&#…

java Web线上网游商品交易平台用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 jsp线上网游商品交易平台是一套完善的web设计系统&#xff0c;对理解JSP java SERLVET mvc编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0…

基于springboot的交通管理在线服务系统的开发

传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装交通管理在线服务系统软件来发挥其高效地信息处理的作用&#xff0…

【数据结构】常见线性结构

1.线性表 线性表 &#xff08; linear list &#xff09; 是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一…

Fiddler抓包工具之fiddler的常用快捷键

一、常用三个快捷键 ctrlX :清空所有记录 CtrlF&#xff1a;查找 F12&#xff1a;启动或者停止抓包 使用 QuickExec Fiddler2 成了网页调试必备的工具&#xff0c;抓包看数据。Fiddler2自带命令行控制。 fiddler 命令行快捷键&#xff1a;ctrl q &#xff0c;然后 输入 help…

约瑟夫环问题(队列,链表实现)- c++

1.关于约瑟夫问题 约瑟夫斯领导犹太人反抗罗马帝国的统治&#xff0c;在与罗马军队的激烈战斗中&#xff0c;与士兵们一同被困在一个山洞里。总共有41人&#xff0c;约瑟夫斯希望向罗马军队投降&#xff0c;但他的士兵们却坚决拒绝&#xff0c;宁愿死也不愿被敌人俘虏。面对这…

国家中英文名称、国家代码(地区代码)、国家域名、经纬度

因为要做世界地图对世界国家的标点&#xff0c;搜索使用到了世界各个国家的地理位置信息&#xff0c;此处做备份与学习。资源地址&#xff08;免费&#xff09; export default {"阿尔巴尼亚": {"m_longitude": "19.809","m_latitude&quo…

React项目打包优化-包体积分析

1、什么是包体积分析&#xff1f; 通过可视化的方式&#xff0c;直观的看到各种包打包之后的体积大小&#xff0c;方便后续针对体积情况做优化 2、怎么分析包&#xff1f; 借助插件 source-map-explorer&#xff0c; 1、先安装插件 npm install source-map-explorer 2、在p…

Consul集群搭建看这篇就够了(consul cluster configuration )

Consul 是一种用于服务发现、配置和分布式一致性的开源工具和平台。它由 HashiCorp 公司开发和维护&#xff0c;旨在简化构建和维护分布式系统的任务。 Consul 提供了许多功能&#xff0c;包括&#xff1a; 服务发现&#xff1a;Consul允许服务注册和发现。当服务启动时&#…

JAVA-----

标识符 标识符可以简单的理解为一个名字&#xff0c;在Java中&#xff0c;我们需要给代码中的很多元素起名字&#xff0c;包括类名、方法名、字段名、变量名等等。我们给对应元素起的名称就被叫做是标识符。一个正确的标识符需要遵循以下规则&#xff1a; 1.标识符可以由字母、…