精华内容
下载资源
问答
  • ack
    更多相关内容
  • 由于公司提供的队列实在太过于蛋疼而且还限制不能使用其他队列,但为了保证数据安全性需要一个可以有ack功能的队列。 原生的redis中通过L/R PUSH/POP方式来实现队列的功能,这个当然是没办法满足需求的(没有ack功能...
  • ack 可以替代 99% 的grep使用。 该插件允许您在 Vim 中使用 ack 进行搜索,并在拆分窗口中显示结果。 但这里的Vim的调味一个小秘密:它只是Vim的轻包装和对比赛结果的窗口。 这使得与您自己的 Vim 配置集成并使用...
  • ack是一种代码搜索工具,类似于grep,但已为程序员搜索大型源代码树进行了优化。 它在纯Perl中运行,具有高度的可移植性,并且可以在运行Perl的任何平台上运行。 ack由Andy Lester( )编写和维护。 项目主页: ...
  • helm-ack:应用程序

    2021-05-15 04:55:59
    helm-ack.el是App :: ack头盔界面。 我建议您使用代替helm-ack。 helm-ag提供了比helm-ack更多的功能,而且helm-ag也支持ack。 截屏 要求 Emacs 24或更高 掌舵1.0或更高 或ack-grep debian软件包。 基本用法 helm-...
  • ejabberd stan ack v0.6 当ejabberd服务器已收到您的消息时,此模块将向您的发件人发送确认/确认消息,而当邮件的收件人已收到您的消息时,此模块将发送另一条确认/确认消息。 在这方面,它提供与移动聊天应用程序...
  • 确认类型 按文件名查找确认类型用法 var acktypes = require ( 'ack-types' )// acktypes is an object mapping file extension to typeacktypes . compare ( filename , type ) // true or falseacktypes . lookup ...
  • 阿里云ACK技术简介及实践.pptx
  • ack-etcd备份资源

    2021-01-15 15:24:00
    ack-etcd备份资源
  • AcitveMQ是作为一种消息存储和分发组件,涉及到client与broker端数据交互的方方面面,它不仅要担保消息的存储安全性,还要提供额外的手段来确保消息的分发是可靠的。Producer客户端使用来发送消息的,Consumer客户端...
  • 阿里云, 微服务, K8S,ACK
  • 硬件I2C无ACK的解决方法,希望对你们有用,可以有效的解决你们的问题。
  • DHCPack-开源

    2021-07-17 10:59:18
    用于分析 DHCP 数据包交换、检测流氓服务器和服务器攻击的工具。
  • LTE物理层上行链路ACK/NACK信令研究,王璐,,本文根据目前LTE物理层提案研究了上行链路ACK/NACK信令,阐述了子帧结构的演进、系统结构及基于CAZAC序列承载信令的设计方法,并介绍��
  • 用于ack的Emacs前端 ack是一种类似于grep的工具,旨在针对拥有大量异构源代码树的程序员。 可从。 将以下内容添加到您的.emacs中: (add-to-list 'load-path "/path/to/full-ack") (autoload 'ack-same "full-ack...
  • ACKack

    2022-06-08 16:59:50
    包含ACKack的区别,一个样例中名词解释

    (1)ACK字段(即上图的32位确认序号):该字段存放的信息为期望收到对方下一个报文段的第一个数据字节的序号。

    (2)ack字段(即上图的6个标志位之一ACK标志位):在TCP报文段中,字段ack=1时,确认号字段才有效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1。

    如下图所示,sun发送的ack都是1,是确保确认号有效而设立的,而bsdi返回的ack是ACK(确认序号)(题目给的ack不用在意)是确认序号,都是上一个报文段末尾+1。

    win为窗口。

    SYN后面带的长串是ISN(Inital Sequence Number)。后面的ACK数值都是相对偏移量(相对于ISN往后偏移了多少),所以ISN只有在建立连接时出现。

    展开全文
  • NERDtree + Ack.vim 该插件增加了通过NERDtree在文件夹中搜索的功能。 搜索使用来自master分支( )的ack.vim。 这是Tudor Barbu从。 只是不符合我的口味,所以,是的。如何安装首先从安装ack.vim。 或者,您可以...
  • TCP Delayed ACK 辩证考

    千次阅读 2022-06-15 22:54:42
    TCP Delayed ACK 的 WiKi 解释: ​ 看下红框里说的“某些劣化性能的场景”: ​ 是不是很复杂?特别是跟 Nagle 算法,糊涂窗口综合症揉在一起,需要理解各种情况如何组合这些配置。复杂的根源在哪儿?先看 Delayed ...

    TCP Delayed ACK 的 WiKi 解释:
    在这里插入图片描述
    看下红框里说的“某些劣化性能的场景”:
    在这里插入图片描述
    是不是很复杂?特别是跟 Nagle 算法,糊涂窗口综合症揉在一起,需要理解各种情况如何组合这些配置。

    复杂的根源在哪儿?

    先看 Delayed ACK 的目标:减少 Pure ACK 数量,提升有效载荷率。

    再看 Nagle 算法的目标:减少小包数量,提升有效载荷率。

    二者的目标一致,为何会冲突?

    根源在于 Delayed ACK 在接收端,Nagle 算法在发送端,不知道对端情况。两端对不齐,仅靠猜肯定不行。

    TCP 在 1981 年被 RFC793 标准化,Delayed ACK 在 1989 年 RFC1122 中发布,Nagle 算法在 1984年 RFC896中发布,RFC793 定义的 TCP 头没有任何 Delayed ACK 和 Nagle 算法的表达能力,且 RFC1122 和 RFC896 未对 TCP 头进行任何修改。

    找到了根源,解决方案就有了,两个配置统一由发送端决定。对 TCP 头进行扩展,增加其明确的表达能力:
    在这里插入图片描述

    在这 6 bits 保留空间内找一个 bit,其意义是:

    • b0:对端决定是否立即应答,保持兼容。
    • b1:对端必须立即应答。
      对启用 Nagle 算法的小包,设置上该标志即可。两端可分别升级协议,若其中一端不升级,失去该能力而已。

    令人不解的是,为什么这么多年没有人做这个简单的扩展以提升协议表达能力,反而搞出那么多的原则:

    • 如果服务端配置了xxx,客户端就必须配置xxx
    • 如果服务端没有xxx,客户端就必须xxx

    接着看 Delayed ACK 和 Nagle 算法的共同目标,都为提升网络的载荷率。如果焦点集中在 Delayed ACK 和 Nagle 算法本身而不是它们的目标,很容易重新陷入复杂。

    再小的包也要转发设备和端主机消耗资源来处理,如果 Delayed ACK 和 Nagle 算法只单纯减少了网络数据包数量而卸载了转发设备处理压力的话,那么 LRO/GRO 则同时减少了二者:

    • LRO/GRO 聚合 Data 包减少了接收端需要处理数据包的数量。
    • 聚合后的大块 Data 批量被应答,减少了 ACK 数量。

    LRO/GRO 后的ACK 也可理解为 Delayed ACK,只是将 Delay 下放在批量收集 Data 的逻辑中。我之前也做实验验证过,开启和未开启 LRO/GRO ,吞吐性能相差近一倍,根源就是未开启 LRO/GRO 时过多的 Data 和 ACK 线性消耗了元数据处理开销。

    一辆车运 100 千克,运 1 吨需要 10 辆车 10 个司机,一辆车运 1 吨,只需要 1 辆车 1 个司机。

    LRO/GRO 的代价是需要增加一点聚合延时。

    可无论再怎么聚合,一个 IP 包最大容量也就 64KB,Delayed ACK 也就能 skip 2*64KB 字节确认一回,但也仅此而已。最近的 BIG TCP patch 差不多就是优化这个问题的:
    tcp: BIG TCP implementation

    这些复杂的方案都没有从根源上解决问题,但好处是只需要修改两端中的一端就能有不错效果。

    如何从根源解决问题,需要通过提升 TCP 协议表达能力最大化 Delayed ACK 收益。仍从 TCP 协议头入手,这次借用 2 个 bits,当然了,这 2bits 也可以在 option 中实现:

    • b00:对端决定是否立即应答,保持兼容。
    • b01:对端必须立即应答。
    • b10:除非 RFC 要求必须立即应答的情况,建议对方不应答。
    • b11:N/A

    发送端统一决定 ACK 的频率,又不影响拥塞状态机。

    发送端可如下决策,不影响采样的前提下,每间隔 10*64KB 的距离设置一次 b10 。这将使 Pure ACK 数量大大减少,达到 Data 和 ACK 的 640:1 的数量比,为网络设备和端主机减负。

    同样令我不解,30年来没人改动过 TCP 的这些逻辑,倒也不是说不好升级,问题是 SACK,Timestamps,Fast Open 不都是后加进去的吗?考虑到兼容性,这些均通过 TCP option 协商决定。为什么 Delayed ACK 不呢?而且它可以天然兼容,甚至不必协商。

    在我看来,数据包是否需要被 ACK 的标志位和 PSH 标志位没什么两样。

    令人遗憾但却有趣的事是,QUIC 竟然继承了 TCP 关于什么时候发送 ACK 的机制,没有把该权力权力统一交给发送端。我想 QUIC 设计时并没有考虑单机性能问题吧,因为单机性能问题 TCP 也没多考虑。

    最新的 RFC9114 还没细看,这里说一个三年前我做的一件事,典型的因 QUIC 表达能力不足把事情复杂化的有关单机性能的 case。

    运行 QUIC 后 CPU 变高,发现 QUIC 的 Data/Pure ACK 数量比太高,ACK copy 到用户态以及上下文切换开销太大。TCP 那么多 ACK 没有表现出太大单机性能问题,部分原因是 ACK 不需要copy 到用户态处理。

    我想了一个点子,内核 GRO 这个位置捕捉相同 UDP 五元组,尽可能将 UDP 报文聚合在一起,考虑到 QUIC 是加密的,不便在内核解密,将被聚合的 UDP Payload 用 TLV(Type-Length-Value) 分隔后拼接,最终加一个 UDP 头统一上送,待一个大 UDP 包收到用户态后,在库层面通过 TLV 分成原始的 QUIC Payload,交给程序处理。

    CPU 降了,可 Delivery rate 相对不准了,这分明是聚合 UDP 小包时的额外延时引入的误差。总体看来,我的这番折腾其实就是 TCP LRO/GRO 在接收端做的那些事。

    看起来做了一件足够复杂且有点技术含量的事,但并没从根本上解决问题。根本解法就是 QUIC 发送端根据数据采集需要以及资源能力,自己决定 Pure ACK 的频度。

    有时候确实是没有消息就是好消息,TCP 的 ACK 自时钟被认为是理所当然的,但实际上那也只是一种手段。

    考虑原始 TCP,接收端将为每一个 Data 包回送一个 ACK,若全世界的流量均是 TCP-Based,那么整个网络 50% 的数据包都是 ACK,50% 以数量记账的资源将被 ACK 消耗,因此减少 ACK 的数量,也是在为整个互联网减负。新生传输协议要多学好,不要比烂。

    好了,这就是我今天要讲的故事。

    想起了几年前做过的和单机性能有关的一例 case,结合 TCP Delayed ACK,写篇短文。

    浙江温州皮鞋湿,下雨进水不会胖。

    展开全文
  • 确认3 ack是一种代码搜索工具,类似于grep,但已为程序员搜索大型源代码树进行了优化。 它具有高度的可移植性,可以在运行Perl的任何平台上运行。 ack由Andy Lester( )编写和维护。邮件列表,仅公告 ,用于 ,用于...
  • 该软件包用于执行不带ACK的TCP握手,这对于TCP健康状况检查很有用。 HAProxy完全相同,即: 同步 同步确认 RST 多年来,这种实现已在成千上万的生产服务器上运行。 为什么我必须这样做 在大多数情况下,当您建立...
  • 介绍Rabbitmq的手动ACK和自动ACK 当消息一旦被消费者接收,队列中的消息就会被删除。那么问题来了:RabbitMQ怎么知道消息被接收了呢? 这就要通过消息确认机制(Acknowlege)来实现了。当消费者获取消息后,会向...

    文章首发于我的个人博客,到个人博客体验更佳阅读哦

    https://www.itqiankun.com/article/1564534513

    介绍Rabbitmq的手动ACK和自动ACK

    当消息一旦被消费者接收,队列中的消息就会被删除。那么问题来了:RabbitMQ怎么知道消息被接收了呢?

    这就要通过消息确认机制(Acknowlege)来实现了。当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。不过这种回执ACK分两种情况:

    • 自动ACK:消息一旦被接收,消费者自动发送ACK
    • 手动ACK:消息接收后,不会发送ACK,需要手动调用

    这两ACK要怎么选择呢?这需要看消息的重要性:

    • 如果消息不太重要,丢失也没有影响,那么自动ACK会比较方便
    • 如果消息非常重要,不容丢失。那么最好在消费完成后手动ACK,否则接收消息后就自动ACK,RabbitMQ就会把消息从队列中删除。如果此时消费者宕机,那么消息就丢失了。

    自动ACK

    自动ACK的演示流程

    Pom.xml代码如下

    <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>cn.itcast.rabbitmq</groupId>
    	<artifactId>itcast-rabbitmq</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.0.4.RELEASE</version>
    	</parent>
    	<properties>
    		<java.version>1.8</java.version>
    	</properties>
    	<dependencies>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-amqp</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    		</dependency>
    	</dependencies>
    </project>
    

    首先工具类代码如下

    package cn.itcast.rabbitmq.util;
    
    import com.rabbitmq.client.ConnectionFactory;
    import com.rabbitmq.client.Connection;
    
    public class ConnectionUtil {
        /**
         * 建立与RabbitMQ的连接
         * @return
         * @throws Exception
         */
        public static Connection getConnection() throws Exception {
            //定义连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            //设置服务地址,设置自己的服务器密码
            factory.setHost("******");
            //端口
            factory.setPort(5672);
            //设置账号信息,用户名、密码、vhost
            factory.setVirtualHost("/***");
            factory.setUsername("***");
            factory.setPassword("***");
            // 通过工程获取连接
            Connection connection = factory.newConnection();
            return connection;
        }
    
    }
    

    然后是生产消息方代码

    下面的代码我在debug之后,当下面的蓝色代码执行完毕之后,在rabbitmq里面的Connections里面就有下面的展示,这就表示发送方的链接和rabbitmq已经连上了

    然后当执行完下面的红色代码的时候,在rabbitmq里面的Channels里面就有下面的展示,这就表示发送方的通道创建好了

    然后下面的黄色代码执行完毕之后,在rabbitmq的队列里面就有Hello World!这个消息了,此时我们可以看到这个消息还没有被消费

    然后我们点击上面的红框里面的东西,然后在点击下面的东西,就可以看到我们刚刚发送的消息

    因为有下面的绿色代码,所以发送方在执行之后,rabbitmq里面的Connections的发送链接就关闭了,rabbitmq里面的Channels的通道链接就关闭了,所以此时rabbitmq里面的Connections是下面这样

    此时rabbitmq里面的Channels是下面这样

    package cn.itcast.rabbitmq.simple;
    
    import cn.itcast.rabbitmq.util.ConnectionUtil;
    
    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.MessageProperties;
    /**
     * 生产者
     */
    public class Send {
    
        private final static String QUEUE_NAME = "simple_queue";
    
        public static void main(String[] argv) throws Exception {
    	 	//蓝色代码注释开始
            // 获取到连接
            Connection connection = ConnectionUtil.getConnection();
    		//蓝色代码注释结束
    		//红色代码注释开始
            // 从连接中创建通道,使用通道才能完成消息相关的操作
            Channel channel = connection.createChannel();
    		//红色代码注释结束
            // 声明(创建)队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    		//黄色代码注释开始
            // 消息内容
            String message = "Hello World!";
            // 向指定的队列中发送消息
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            System.out.println(" [x] Sent '" + message + "'");
    		//黄色代码注释结束
    		//绿色代码注释开始
            //关闭通道和连接
            channel.close();
            connection.close();
    		//绿色代码注释结束
        }
    }
    

    然后是接受方接受消息的代码

    Pom.xml代码如下

    <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>cn.itcast.rabbitmq</groupId>
    	<artifactId>itcast-rabbitmq</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.0.4.RELEASE</version>
    	</parent>
    	<properties>
    		<java.version>1.8</java.version>
    	</properties>
    	<dependencies>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-amqp</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    		</dependency>
    	</dependencies>
    </project>
    

    下面的当下面的蓝色代码执行完毕之后,在rabbitmq里面的Connections里面就有下面的展示,这就表示接受方的链接和rabbitmq已经连上了

    然后当执行完下面的红色代码的时候,在rabbitma里面的Channels里面就有下面的展示,这就表示接受方的通道创建好了

    下面的绿色代码表示创建一个消费对象,这个消费者并且有一个监听事件,如果有消息的时候,会被自动调用,下面的黄色代码表示把队列和消费者绑定到一起,当执行完毕之后,队列里面的消息就会没有了

    此时要注意当接受消息之后,rabbitmq里面的queues里面的消息就会被删除了

    注意因为下面的接受方没有连接和通道的关闭,所以此时的接收方的Connections连接和channels通道连接还是一直没有关闭的
    你可以看到这里的程序一直没有停

    然后接收方的Connections连接也没有消失

    然后此时Idea接收方的channels连接也没有消失,
    然后我们手动关闭这个接受方的程序,就是点击这个红色按钮

    然后rabbitmq里面的Connections的发送链接就关闭了,rabbitmq里面的Channels的通道链接就关闭了,所以此时rabbitmq里面的Channels是下面这样

    
    package cn.itcast.rabbitmq.simple;
    
    import java.io.IOException;
    
    import com.rabbitmq.client.AMQP.BasicProperties;
    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.DefaultConsumer;
    import com.rabbitmq.client.Envelope;
    
    import cn.itcast.rabbitmq.util.ConnectionUtil;
    
    /**
     * 消费者
     */
    public class Recv {
        private final static String QUEUE_NAME = "simple_queue";
    
        public static void main(String[] argv) throws Exception {
    	    // 蓝色代码开始
            // 获取到连接
            Connection connection = ConnectionUtil.getConnection();
    		// 蓝色代码结束
    		// 红色代码开始
            // 创建通道
            Channel channel = connection.createChannel();
    		// 红色代码结束
            // 声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    		// 绿色代码开始
            // 定义队列的消费者
            DefaultConsumer consumer = new DefaultConsumer(channel) {
                // 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties,
                        byte[] body) throws IOException {
                    // body 即消息体
                    String msg = new String(body);
                    System.out.println(" [x] received : " + msg + "!");
                }
            };
    		// 绿色代码结束
    		// 黄色代码开始
            // 监听队列,第二个参数:是否自动进行消息确认。
            channel.basicConsume(QUEUE_NAME, true, consumer);
    		// 黄色代码结束
        }
    }
    
    自动ACK的缺点

    工具类代码如下所示

    package cn.itcast.rabbitmq.util;
    
    import com.rabbitmq.client.ConnectionFactory;
    import com.rabbitmq.client.Connection;
    
    public class ConnectionUtil {
        /**
         * 建立与RabbitMQ的连接
         * @return
         * @throws Exception
         */
        public static Connection getConnection() throws Exception {
            //定义连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            //设置服务地址
            factory.setHost("47.91.248.236");
            //端口
            factory.setPort(5672);
            //设置账号信息,用户名、密码、vhost
            factory.setVirtualHost("/leyou");
            factory.setUsername("leyou");
            factory.setPassword("leyou");
            // 通过工程获取连接
            Connection connection = factory.newConnection();
            return connection;
        }
    
    }
    

    比如下面的代码
    首先pom.xml代码如下所示

    <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>cn.itcast.rabbitmq</groupId>
    	<artifactId>itcast-rabbitmq</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.0.4.RELEASE</version>
    	</parent>
    	<properties>
    		<java.version>1.8</java.version>
    	</properties>
    	<dependencies>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-amqp</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    		</dependency>
    	</dependencies>
    </project>
    

    然后发送方的代码如下所示

    package cn.itcast.rabbitmq.simple;
    
    import cn.itcast.rabbitmq.util.ConnectionUtil;
    
    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.MessageProperties;
    /**
     * 生产者
     */
    public class Send {
    
        private final static String QUEUE_NAME = "simple_queue";
    
        public static void main(String[] argv) throws Exception {
            // 获取到连接
            Connection connection = ConnectionUtil.getConnection();
            // 从连接中创建通道,使用通道才能完成消息相关的操作
            Channel channel = connection.createChannel();
            // 声明(创建)队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            // 消息内容
            String message = "Hello World!";
            // 向指定的队列中发送消息
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            
            System.out.println(" [x] Sent '" + message + "'");
    
            //关闭通道和连接
            channel.close();
            connection.close();
        }
    }
    

    然后执行发送方的代码,然后消息队列里面就会有这个消息了

    然后接受方代码如下所示,注意下面的绿色代码抛出异常了,然后此时我们执行接收方的代码,下面的蓝色代码表示自动进行ack

    package cn.itcast.rabbitmq.simple;
    
    import java.io.IOException;
    
    import com.rabbitmq.client.AMQP.BasicProperties;
    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.DefaultConsumer;
    import com.rabbitmq.client.Envelope;
    
    import cn.itcast.rabbitmq.util.ConnectionUtil;
    
    /**
     * 消费者
     */
    public class Recv {
        private final static String QUEUE_NAME = "simple_queue";
    
        public static void main(String[] argv) throws Exception {
            // 获取到连接
            Connection connection = ConnectionUtil.getConnection();
            // 创建通道
            Channel channel = connection.createChannel();
            // 声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            // 定义队列的消费者
            DefaultConsumer consumer = new DefaultConsumer(channel) {
                // 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties,
                        byte[] body) throws IOException {
                    // body 即消息体
                    String msg = new String(body);
    				//绿色代码开始
                    int i=1/0;
    				//绿色代码结束
    				//红色代码开始
                    System.out.println(" [x] received : " + msg + "!");
    				//红色代码结束
                }
            };
    		//绿色代码开始
            // 监听队列,第二个参数:是否自动进行消息确认。
            channel.basicConsume(QUEUE_NAME, true, consumer);
    		//绿色代码结束
    
        }
    }
    

    执行接收方代码之后,结果如下所示,此时可以看到根本没有执行上面的红色代码,也就是说此时不算接受成功(此时如果红色代码是重要的逻辑代码,那么在实际开发里面不就有问题了)

    但是此时可以看到rabbitmq里面的消息队列里面的消息已经没有了,这就是自动ack的缺点

    手动ack解决自动ack的缺点

    工具类代码如下所示

    package cn.itcast.rabbitmq.util;
    
    import com.rabbitmq.client.ConnectionFactory;
    import com.rabbitmq.client.Connection;
    
    public class ConnectionUtil {
        /**
         * 建立与RabbitMQ的连接
         * @return
         * @throws Exception
         */
        public static Connection getConnection() throws Exception {
            //定义连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            //设置服务地址
            factory.setHost("47.91.248.236");
            //端口
            factory.setPort(5672);
            //设置账号信息,用户名、密码、vhost
            factory.setVirtualHost("/leyou");
            factory.setUsername("leyou");
            factory.setPassword("leyou");
            // 通过工程获取连接
            Connection connection = factory.newConnection();
            return connection;
        }
    
    }
    

    比如下面的代码
    首先pom.xml代码如下所示

    <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>cn.itcast.rabbitmq</groupId>
    	<artifactId>itcast-rabbitmq</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.0.4.RELEASE</version>
    	</parent>
    	<properties>
    		<java.version>1.8</java.version>
    	</properties>
    	<dependencies>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-amqp</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    		</dependency>
    	</dependencies>
    </project>
    

    然后发送方的代码如下所示

    package cn.itcast.rabbitmq.simple;
    
    import cn.itcast.rabbitmq.util.ConnectionUtil;
    
    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.MessageProperties;
    /**
     * 生产者
     */
    public class Send {
    
        private final static String QUEUE_NAME = "simple_queue";
    
        public static void main(String[] argv) throws Exception {
            // 获取到连接
            Connection connection = ConnectionUtil.getConnection();
            // 从连接中创建通道,使用通道才能完成消息相关的操作
            Channel channel = connection.createChannel();
            // 声明(创建)队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            // 消息内容
            String message = "Hello World!";
            // 向指定的队列中发送消息
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            
            System.out.println(" [x] Sent '" + message + "'");
    
            //关闭通道和连接
            channel.close();
            connection.close();
        }
    }
    

    然后执行发送方的代码,然后消息队列里面就会有这个消息了

    然后接受方代码如下所示,注意下面的绿色代码抛出异常了,然后此时我们执行接收方的代码,此时红色代码就表示手动进行ack

    package cn.itcast.rabbitmq.simple;
    
    import java.io.IOException;
    
    import com.rabbitmq.client.AMQP.BasicProperties;
    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.DefaultConsumer;
    import com.rabbitmq.client.Envelope;
    
    import cn.itcast.rabbitmq.util.ConnectionUtil;
    
    /**
     * 消费者,手动进行ACK
     */
    public class Recv2 {
        private final static String QUEUE_NAME = "simple_queue";
    
        public static void main(String[] argv) throws Exception {
            // 获取到连接
            Connection connection = ConnectionUtil.getConnection();
            // 创建通道
            final Channel channel = connection.createChannel();
            // 声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            // 定义队列的消费者
            DefaultConsumer consumer = new DefaultConsumer(channel) {
                // 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties,
                        byte[] body) throws IOException {
                    // body 即消息体
                    String msg = new String(body);
    				//绿色代码开始
                    int i=1/0;
    				//绿色代码结束
    				//红色代码开始
                    System.out.println(" [x] received : " + msg + "!");
                    // 手动进行ACK
                    channel.basicAck(envelope.getDeliveryTag(), false);
    				//红色代码结束
                }
            };
    		//红色代码开始
            // 监听队列,第二个参数false,手动进行ACK
            channel.basicConsume(QUEUE_NAME, false, consumer);
    		//红色代码开始
        }
    }
    

    执行接收方代码之后,结果如下所示,此时可以看到根本没有执行上面的红色代码,也就是说此时不算接受成功

    但是此时可以看到rabbitmq里面的消息队列里面的消息还是有的,这就是手动ack解决了自动ack的缺点

    展开全文
  • pagerduty_ack_to_nagios

    2021-05-10 12:44:38
    请参考是新的权威上游pd_ack_to_nagios_ack_poller.pl 补充 pagerduty_nagios.pl很好地完成了将nagios事件纳入pagerduty的工作。此脚本提供了相反的功能,从而实现了往返同步的更多体验更具体地说,它将轮询自上次...
  • 消费者签收消息(ACK)2.1 代码实现源代码 一、RabbitMQ 高级特性 基础案例环境搭建: 基础环境搭建(手把手教你环境搭建和五种工作模式):...
  • TCP延迟ACK策略

    千次阅读 2019-05-13 21:02:44
    在报文接收路径上,处理完报文的接收之后,使用函数__tcp_ack_snd_check检查是否需要发送ACK确认报文。如果不符合立即发送的条件,内核将延迟发送ACK确认报文。 1)接收到一个以上的全尺寸报文; 2)a)接收窗口增长...
  • TCP ACK状态

    千次阅读 2019-05-14 20:48:30
    如下定义,TCP的ACK状态由如下4个。 enum inet_csk_ack_state_t { ICSK_ACK_SCHED = 1, ICSK_ACK_TIMER = 2, ICSK_ACK_PUSHED = 4, ICSK_ACK_PUSHED2 = 8 }; 初始状态 在TCP套接口初始化时,注册延迟ACK等一...
  • seq和ack号存在于TCP报文段的首部中,seq是序号,ack是确认号,大小均为4字节(注意与大写的ACK不同,ACK是6个控制位之一,大小只有一位, 仅当 ACK=1 时ack字段才有效。建立 TCP 连接后,所有报文段都必须把 ...
  • RocketMQ消息ACK机制

    千次阅读 2022-04-01 16:12:14
    最详细的RocketMQ Ack机制分析
  • 阿里云ACK初体验

    千次阅读 2022-02-28 22:29:28
    阿里云容器服务Kubernetes版(Alibaba Cloud Container Service for Kubernetes,简称容器服务ACK)是全球首批通过Kubernetes一致性认证的服务平台,提供高性能的容器应用管理服务,支持企业级Kubernetes容器化应用...
  • 伪造ACK实现TCP数据注入

    千次阅读 2021-04-04 12:49:18
    在TCP伊始,最重要的是可用,而不是高效,也不是安全,因此,在端到端TCP连接的中间,利用伪造的ACK,你很容易完成一种叫做 中间人攻击 的事情。 如果你用“TCP劫持”,“TCP中间人”,“TCP注入”等作为关键词百度...
  • } catch (Exception e) { //捕获异常后,重新发送到指定队列,自动ack不抛出异常即为ack channel.basicPublish(msg.getMessageProperties().getReceivedExchange(), msg.getMessageProperties()....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 265,386
精华内容 106,154
关键字:

ack

友情链接: Ov chipkaart hacker.zip