Netty in Action (二十四) 第十三章节 UDP的广播事件

本章内容包括:

1)UDP的总览

2)广播应用的一个简单示例

到目前为止,我们使用的所有例子都是基于连接形式的协议,例如TCP,在这个章节中,我们将会聚焦于无连接x形式的协议(User Datagram Protocol UDP),这个协议常常使用于对性能要求极其高但又可以允许少量的丢包的情况存在

我们先讲解一下UDP的概念,讲解一下它的特性和限制,接下来我们会描述一下这个章节示例应用的业务背景,这个示例将会很好的说明如何使用UDP协议的广播特性,我们也会利用解码器和编码器来处理一个POJO,在这个章节的最后部分,你应该可以使用UDP协议应用到你的项目中

13.1 UDP basics

基于连接的传输服务例如TCP这类类型的协议管理着两个终端之间建立的连接,在连接的整个生命周期里,信息可以有序的可信赖的传输,在连接的中断的时候可以有序地关闭终端,相反,像UDP这类无连接的协议,是没有稳固耐用的连接,每个信息都是一个独立的传输体

还有就是UDP没有TCP协议存有的那个纠错的机制,这种机制是指每个终端当它收到一个消息包的时候,都会给出一个反馈,没给返回的包,发送者将会重新发送

对比一下,一个TCP连接就像一个电话通信,在这个通信中信息可以在两个终端有序的传播,相反,UDP就像邮箱里的一堆明信片,你无法知道它们到达邮箱的先后顺序,甚至都不能知道是否所有的明信片是否已经全部收到

因为这些UDP协议的这些局限性可能会限制你,但是这也很好的解释了为什么UDP协议快于TCP,握手阶段的性能损耗和消息管理被消除了,很明显,UDP对于那些可以接受消息部分损失的系统将是一个非常好的选择,当然这种协议是不适用金融信息传输的

13.2 UDP broadcast

到目前为止我们使用的传输模式被称为“单点传播”,单点传播的定义是这样的:消息的发送只会发送到由唯一地址确认的网络目的地,这种模式可以被有链接和无连接的两种协议所支持,UDP提供了其他额外的传输模式用来发送信息给多个收件人

1)组播(Multicast)----------传输到定义好的一组终端里

2)广播(Broadcast)--------------传输到整个网络中的所有host中

在我们这个章节的示例应用中,来说明UDP的广播机制,通过将信息发送到同一个网络的所有host,出于这个目的,我们将使用特殊的受限制的广播零点网络地址255.255.255.255,信息将会传送到这个地址,这将是本地网络所有host的地址,并且不会被路由器转送到其他的网络中

接下来我们将会讨论这个应用的设计

13.3 The UDP sample application

我们的示例应用将会打开一个文件然后将文件的每一行数据都当做一种信息通过UDP指定的具体端口进行广播,如果你对类Linux的操作系统很熟悉的话,你可以将这种业务场景想象成syslog功能的简化版,那么UDP对于这样类似的场景是很适用的,因为日记文件的偶尔的行损失是完全可以被接受的,给以的文件存储在文件系统中,还有就是这种方案提供了一个非常有价值的高效的解决大数据量传输的方案

那么关于接收者的设定呢?如果使用UDP的广播机制,那么你可以创建一个事件管理器来接收日记信息,我们可以简单地启动一个监听程序,这个程序在某个具体的端口监听,注意这种太过容易的访问会引起潜在的安全问题,这也是为什么UDP协议不会用在不安全的环境中的原因之一,因为这样同样的原因,路由器经常会阻塞信息的广播,限制他们只能在他们起源的网络段中

发布/订阅:像syslig这样的应用是典型的“发布订阅”类型的系统,一个生产者或者一个服务发布事件,多个客户端订阅这个事件然后接收他们

图13.1展示了这个应用系统的俯瞰图,它包含了对一个或者多个事件管理器的广播,这个广播监听是否有新的内容出现,如果它出现了,将它用UDP协议将其当做一种广播信息传播出去

所有的时间管理者监听着UDP的端口来接收广播的信息

为了让我们的示例尽可能的保持简单,我们不会将授权,验证,加密这些组件加入到我们这个简单的应用中去,但这并不意味着将这些特性混合使用很难,将这些组件组合在一起对于Netty来说很简单,且这些组件可以增加应用的健壮性,实用性

在下一个章节中,我们将开始探索广播组件的设计和实现细节

13.4 The message POJO: LogEvent

在消息应用中,数据经常是由一个POJO来表示的,这个POJO中包含一些配置信息或者一些处理的信息甚至还有一些真实的信息内容,在这个应用中,我们将处理信息当做一种事件,这是因为数据是来自于日记文件的,所以我们将其命名为“LogEvent”,代码清单展示了这个POJO的细节

我们已经定义了消息组件,我们可以实现应用系统的广播的逻辑了,在下一个章节,我们将学习Netty框架提供的一些类,这些类可以用来对LogEvent消息对象的编码和传输

13.5 Writing the broadcaster

Netty提供了一定数量的类用来支持UDP应用代码编写,我们主要使用的几个类就是消息容器和Channel的类型,我已经在13.1中一一列出了:

Netty的DatagramPacket是一个简单的信息容器,再使用DatagramChannel的具体实现可以很方便地进行终端的通讯,在我们之前提及的一样,我们举得明信片的例子,这个明信片中包含了收件人的地址也可能会有发件人的地址,还有信息本身承载的一些信息

为了将EventLog信息转化成DatagramPackets,我们需要一个编码器,当然我们不需要自己从零开始写,我们可以使用第九章和第十章介绍的MessageToMessageEncoder来帮助我们完成这样的工作

图13.2展示了三个log对象的广播,每一个Entity都有它们对应的专有的DatagramPacket

图13.3展示了LogEventBroadcaster的ChannelPipeline的高级层次图,展示了LogEvent如何在里面流动的

你可以看见所有的数据都被封装成LogEvent消息格式来传输,LogEventBroadcaster将LogEvent写入到channel中,将其通过管道发送,在此之前,这些消息可能会被编码成DatagramPacket消息格式来传播,最后他们将会被UDP广播,最后被终端获取到

下面的代码清单展示了我们定制的MessageToMessageEncoder,它将会完成我们之前讨论的那些功能

伴随着LogEventEncoder的实现,我们现在开始准备启动服务端,这个服务端需要设置一些启动参数,并且需要安装一些需要的ChannelHandler到管道中,这都将由LogEventBroadcaster的方法完成,如下面代码清单所示:

这就完成了你应用的广播组件了,测试的开始阶段,你可以使用netcat,在UNIX/Linux系统上你可以找到nc软件安装,Windows的版本下载可以在http://nmap.org/ncat中下载

netcat很适用于一个软件最基本的测试,它做的事情很简单:在某个端口上监听,打印出这个端口接收到的所有数据,在我们这个项目中我们我们可以通过如下的命令设置在9999端口监听UDP数据

现在我们需要启动我们的LogEventBroadcaster,下面的启动日记展示了如何使用mvn去编译然后运行广播器,在pom.xml中指定的那个文件是经常被变更的,加入在linux环境下设置文件的路径为“/var/log/messages/”,并且设置端口号是9999,那么这个文件将通过UDP的广播接收到广播的信息,然后当我们启动netcat的时候,就能记录所有控制台输出的所有信息

如果想要改变文件的输出路径和端口号,我们可以在运行mvn命令的时候以系统变量的形式去重新指定值,下面的日记输出展示了如何重新设置log的路径和端口号的

当你在日记信息中看见LogEventBroadcaster能够正常运行,你就可以确认知道它已经成功启动了,如果有错误,那么错误信息将会被打印出,一个错误的信息将会被打印,一旦进程在运行的时候,它将会广播每一条log信息将其增加到log文件中

使用netcat很适合我们应用的测试,但是对于应用于生产环境的系统来说,这是不太适用的,因为这个原因,我们需要开发我们应用的第二个模块,广播监控者,下一个小节,我们将实现这个功能

13.6 Writing the monitor

我们的目的就是将netcat替换成一个更加完整的事件消费者,这个新的功能我们称之为EventLogMonitor,这段程序的功能是这样的:

1)接收LogEventBroadcaster广播的UDP的DatagramPakets

2)将接收的消息解码成LogEvent消息

3)将解码的LogEvent用System.out打印出

与我们之前一样,监控应用的业务逻辑块是由我们自定义的四个解码器完成的,我们继承了MessageToMessageDecoder,图13.4描述了LogEventMonitor的ChannelPipeline,并且展示了LogEvent是如何通过这个管道的

在这个管道中的第一个解码器是LogEventDecoder,它负责将其输入的DatagramPackets转换成LogEvent消息,这是所有的Netty应用一个典型的设置,一开始进行将输入的信息进行转化,下面的代码清单给出了实现

第二个ChannelHandler的作用就是将第一个Channel创建的LogEvent消息进行一些处理,在我们这个简单的案例里,我们只是简单的将其打印出来,可能在真实的生产环境中,你可能会把不同数据源的日记聚合起来然后将聚合的结果存储到数据库中,下面的代码清单展示了LogEventHandler如何完成这项任务的

LogEventHandler将以一种比较易读的方式打印出LogEvent信息,打印出的信息内容包括

1)接收到的时间戳

2)发送者的InetSocketAddres,这个里面包括IP和端口号

3)LogEvent文件产生的绝对路径名

4)真实的日记信息,包含了一行完整的日记输出

现在我们将我们的处理器安装到ChannelPipeline中,就如我们图13.4所示,这个工作将由我们的LogEventMonitor的主函数完成

13.7 Running the LogEventBroadcaster and LogEventMonitor

与我们之前一样,我们使用Maven来运行我们的程序,不过这次我们需要打开两个运行窗口,两个都用来运行程序,每一个都会保持运行的状态,知道你使用Ctrl+C建停止程序

首先,你需要启动LogEventBroadcaste,因为我们之前已经构建过这个应用,所以下面的运行命令就足够了:

从现在开始,它将会通过UDP来开始广播日记信息

现在再打开一个新的窗口,构建和启动LogEventMonitor来接收和展示广播的消息:

当你看见LogEventMonitor运行的时候,你将意识到应用已经成功运行了,如果有错误存在,那么异常信息将会在控制台打印出。

控制台将会展示所有的事件,如下面日记所示,所有的信息格式都是由LogEventHandler规范创建的

如果你不能获取到UNIX的日记,你可以创建一个自定义的文件手动将其应用到你的应用中,下面的命令展示了如何使用这个文件,首先先创建一个空的文件

我们现在开始重启LogEventBroadcaster,通过系统变量指向我们刚才创建的文件

一旦LogEventBroadcaster运行起来,你可以手动地像刚才创建的文件中添加信息,然后你就可以在LogEventMonitor的控制台看到广播出来的信息,使用echo重定向输出到文件中:

你可以任意创建多个监控实例,每一个都会接收打印出同样的信息

13.8 Summary

在这个章节中,我们讲解了UDP这样的无连接的协议,我们构建了一个简单的项目示例,我们将日记信息通过UDP的datagrams形式以广播的方式传播给每一个订阅者,这个实例告诉我们Netty的UDP的使用方式,且UDP可以在一些比较特殊的场景有一些比较独特的运用

在接下来的两个章节中,我们将有幸看见来自世界级公司的开发人员如何运用Netty去构建工业级的应用的

时间: 2024-10-09 19:22:09

Netty in Action (二十四) 第十三章节 UDP的广播事件的相关文章

Netty in Action (十四) 第五章节 第三部分 ByteBufHolder,ByteBuf分配,计数引用

5.4 Interface ByteBufHolder 我们经常在ByteBuf中存储一些正常数据之外,我们有时候还需要增加一些各式各样的属性值,一个Http响应体就是一个很好的例子,除了按照字节传输过来的主体内容,还有状态码,cookie等信息 Netty提供了ByteBufHolder来处理这些常用的用户案例,ByteBufHolder还提供了Netty一些其他的先进特性,例如缓存池,缓存池可以是ByteBuf中直接"借出"获取,如果有需要,"借出"的ByteB

Netty in Action (十九) 第九章节 单元测试

本章内容包括: 1)单元测试 2)EmbeddedChannel的说明 3)使用EmbeddedChannel测试ChannelHandler 对于一个Netty应用来说,ChannelHandler是一个至关重要的元素,所以充分地去测试ChannelHandler应该是你开发过程中必要的组成部分,我们的最佳实践会告诉你测试不仅能保证你的具体实现的正确性,更重要的是,当你突然变更你的代码的时候,它能很容易地去隔离问题,这种类型的测试叫做单元测试 尽管对单元测试大家没有一个完整的定义,但是更多的参

Android学习路线(二十四)ActionBar Fragment运用最佳实践

通过前面的几篇博客,大家看到了Google是如何解释action bar和fragment以及推荐的用法.俗话说没有demo的博客不是好博客,下面我会介绍一下action bar和fragment在实战中的应用,以及相关demo源码,希望和大家相互交流. 了解过fragment的同学们应该都知道,fragment是android 3.0版本才出现的的,因此如果要在支持android 3.0一下版本的工程中使用fragment的话是需要添加Support Library的.具体如何添加我就不再赘述

请对照这二十四条逻辑谬误自行打脸(转自知乎谢熊猫专栏)

[科普工具文]请对照这二十四条逻辑谬误自行打脸 谢熊猫君 · 1 年前 两年前,我还活跃在人人网的时候,曾经整理过一篇常见逻辑谬误的工具文,用来帮助大家在网络讨论中打脸用: [科普工具文]请对照这二十四条逻辑谬误自行打脸 这两年来在一些社交网站和互联网论坛中常看到有人使用这篇文章,想来也是有点用处的,特意在这边转帖一下,为方便各位在知乎讨论时能更加方便的辨别逻辑问题. ======================= ======================= 本文内容基本都来自于英文网站ht

二十四式太极拳

.起势 左脚开立 两臂前举屈膝按掌 二.左右野马分鬃 1.左野马分鬃 稍右转体 收脚抱球 转体上步 弓步分手 2.右野马分鬃 坐撇脚 收脚抱球 转体上步 弓步分手 3.左野马分鬃 坐撇脚 收脚抱球 转体上步 弓步分手 三.白鹤亮翅 稍右转体 跟步抱球 坐转体 虚步分手 四.左右搂膝拗步 1.左搂膝拗步 转体摆臂 摆臂收脚 上步屈肘 弓步搂推 2.右搂膝拗步 坐撇脚 摆臂收脚 上步屈肘 弓步搂推 3.左搂膝拗步 坐撇脚 摆臂收脚 上步屈肘 弓步搂推 五.手挥琵琶 跟步展臂 坐引手 虚步合手 六.左

Bootstrap<基础二十四> 缩略图

Bootstrap 缩略图.大多数站点都需要在网格中布局图像.视频.文本等.Bootstrap 通过缩略图为此提供了一种简便的方式.使用 Bootstrap 创建缩略图的步骤如下: 在图像周围添加带有 class .thumbnail 的 <a> 标签. 这会添加四个像素的内边距(padding)和一个灰色的边框. 当鼠标悬停在图像上时,会动画显示出图像的轮廓. 下面的实例演示了默认的缩略图: <!DOCTYPE html> <html> <head> &l

从零开始学android&lt;android事件的处理方式.二十四.&gt;

在android中一共有 多种事件,每种事件都有自己相对应的处理机制 如以下几种 1 单击事件 View.OnClickListener public abstract void onClick (View v) 单击组件时触发 2 单击事件 View.OnLongClickListener public abstract boolean onLongClick (View v) 长按组件时触发 3 键盘事件 View.OnKeyListener public abstract boolean

实验二十四:SD卡模块

  驱动SD卡是件容易让人抓狂的事情,驱动SD卡好比SDRAM执行页读写,SD卡虽然不及SDRAM的麻烦要求(时序参数),但是驱动过程却有猥琐操作.除此此外,描述语言只要稍微比较一下C语言,描述语言一定会泪流满面,因为嵌套循环,嵌套判断,或者嵌套函数等都是它的痛.. 史莱姆模块是多模块建模的通病,意指结构能力非常脆弱的模块,暴力的嵌套行为往往会击垮模块的美丽身躯,好让脆弱结构更加脆弱还有惨不忍睹,最终搞垮模块的表达能力.描述语言预想驾驭SD卡,关键的地方就是如何提升模块的结构能力.简单而言,描述

攻城狮在路上(叁)Linux(二十四)--- linux设置开机挂载及镜像文件挂载

虽然可以手动进行文件系统的挂载,但是每次都手动挂载就会很麻烦,开机挂载的目的就是实现文件系统的自动挂载. 一.开机挂载:/etc/fstab及/etc/mtab 主要是通过修改/etc/fstab文件的配置来实现. fstab是开机时的设置,实际文件系统的挂载是记录到/etc/mtab和/proc/mounts这两个文件中. 1.系统挂载的限制: A.根目录/必须挂载,而且一定是最先挂载的,要先于其他mount point. B.其他挂载点必须为已新建的目录,可以任意指定. C.所有挂载点在同一