赞
踩
消息队列(Message Queue)
是指一种应用程序之间通过异步消息传递来进行通信的方法。消息队列系统通常由消息生产者、消息中间件和消息消费者组成。消息生产者将消息发送到消息队列中,消息中间件负责将消息传递到消息消费者,消息消费者则从消息队列中接收并处理消息。
消息队列的主要优点在于可以实现异步通信,提高系统的可靠性和可扩展性。当系统的业务量增加时,可以通过增加消息队列的数量和容量来满足需求,从而提高系统的性能和可靠性。同时,由于消息队列可以实现消息的持久化存储,即使发生系统故障,也不会丢失消息。
消息队列的应用场景非常广泛,例如:
异步处理:将耗时的操作放到消息队列中异步处理,避免阻塞主线程,提高系统的吞吐量和响应速度。
服务解耦:通过消息队列将服务之间的依赖解耦,降低系统的耦合性,提高系统的可维护性和可扩展性。
流量削峰:通过消息队列将请求分散到不同的服务器上处理,避免单一服务器被请求压垮,从而实现流量削峰。
日志收集:通过消息队列将系统日志收集到中央服务器上,方便进行监控和分析。
常见的消息队列系统包括:
ActiveMQ:是一个开源的消息中间件,支持多种协议和编程语言。
RabbitMQ:是一个开源的AMQP(高级消息队列协议)消息中间件,支持多种编程语言。
Kafka:是一个分布式的消息中间件系统,主要用于处理大数据流。
RocketMQ:是阿里巴巴开源的分布式消息中间件,支持高可靠性、高吞吐量的消息传输。
不同的消息队列系统有着不同的特点和优势,需要根据具体的应用场景进行选择。例如,ActiveMQ适合于需要支持多种协议和编程语言的场景,RabbitMQ适合于需要支持AMQP协议的场景,Kafka适合于处理大数据流的场景,RocketMQ适合于高可靠性和高吞吐量的场景。
前置基础
什么单体架构呢?
不管啥功能都往一个应用里写,比如电商系统。用户功能、商品功能、订单功能等等,都往一个应用里写。
单体应用架构简单粗暴,将所有的功能都打包在一个的应用中,直接部署。
本地开发调试方便,直接起一个项目,调试也是在一个进程内,没有冗长跨进程的调用链,出错可快速定位。
本地的函数调用,没有网络调用的开销。
线上出了问题回滚这一个应用即可(这一点其实在某种程度上看是优点,某种程度上看是缺点)。
总结的说就是开发、测试、部署方便,本地调用对于远程调用性能较好。
那么这样不是挺好的嘛,也方便统一管理了,有什么坏处?
此处引用大佬的一段自我经历:原文链接:https://blog.csdn.net/qq_35190492/article/details/107932805
系统耦合性高,导致开发效率低下。
一开始可能模块结构还很清晰,随着需求日益增长,不断的添加新功能,代码量巨增,模块之间的边界开始模糊,调用关系开始混乱,整体的代码质量非常依赖个人水平。
假使某个同事水平较差,实现的代码冗余,逻辑混乱,这时候要在上面添加新功能或者修改老功能其实是一件很困难的事情,你不能保证你修改的功能模块不会影响到其他功能。
而且代码会有**“破窗效应”**(这里其实不仅仅是单体架构,对于所有架构来说都是如此,只是单体应用更大的庞大,业务界限不清晰,因此这种问题更容易被放大)。
有些人看到这就可能会说,这上面还说开发方便,这就又效率低下了?是的,过犹不及。
再比如一个新需求上线例如短信相关的,并且订单也做了一些改造,但是短信功能出了 bug,需要回滚的是整个应用,订单模块冤啊,陪着一起回滚(看到大佬的这句你的脑海里一定会跳出【耦合】两个大字)。
我在老东家做电商活动,我们上线一个需求可能涉及6、7个服务,回滚也得全部回滚,而且都是负载均衡的,那机器可能就是上百台了。
语言单一,不能根据场景选择更加合适的语言,例如要实现数据分析,应用的语言是 Java,那么就不能利用到 Python 丰富的类库。
系统的整体可靠性不高
什么意思呢?还是拿短信功能说事,新上的短信功能写的有 bug,不管是堆栈溢出还是死循环等等,核心的订单等功能都会受到影响。 因此你上线的功能有问题影响的不仅仅是这个功能模块,可能是整体系统的瘫痪。
系统不易于扩展部署
假设你发现你们的商品查询的流量特别大,顶不住就得加机器。因为是单体应用所以为了商品查询这一个功能,你需要在新加的机器上部署这一个应用,没法单独为这一个功能做定制化部署,对硬件资源有一定的浪费。
总结的说缺点就是随着需求不断增长,代码结构日益复杂,各功能掺杂在一起,系统耦合性高,模块之间边界维护非常依赖开发者的个人水平。
模块之间经常会有公共功能难以划分清楚,添加或修改功能困难,不确定是否会影响到其他模块,所有功能都在一个进程内,某个功能出问题可能影响的就是整个应用,而且无法根据特点场景选择更加合适的语言去实现功能,技术单一。
随着用户的不断增长
无法做到热点功能单独扩展,只能整体应用部署。
至此我们已经明白了单体应用架构的优缺点,可以看出初始阶段单体应用优点突出,随着需求和用户的增长渐渐的单体应用顶不住,缺点在不断的放大。
也就是说你的产品需要发展到一定的阶段,单体应用才会顶不住。在这之前单体应用是你的最佳选择。
你要是说我的产品肯定顶的,所以一开始就大刀阔斧的设计,单体应用太 low 坚决不用。
看下单体应用一般的架构图,注意单体应用不是真的就线上部署一个,好歹得两台,互相 backup 下,不能太虎一台顶。
又过了一段时间,你发现你们还需要开发手机版。于是你们的架构又变成下图所示的样子。
前置术语
什么是集群?
试想一下,当网站莫名出现高并发大流量访问,可以怎么处理呢?
先换硬件?
普通的P4服务器一般最多能支持每天10万独立IP,如果访问量比这个还要大, 就必须首先配置一台更高性能的专用服务器才能解决问题 ,否则怎么优化都不可能彻底解决性能问题。
当然我们知道,当硬件升级到一定程度之后,考虑现有的技术水平和购买成本等因素,你的硬件设备一定会达到一个相对最高点,那你的硬件设备已经达到了你能达到的最高点呢?那你有能怎么办呢?
这里就有一个特殊的概念:负载均衡
负载均衡就是根据某种负载策略把请求分发到集群中的每一台服务器上,让整个服务器群来处理网站的请求。
公司比较有钱的(就当公司没钱吧),可以购买专门负责负载均衡的硬件(如:F5),效果肯定会很好。对于大部分公司,会选择廉价有效的方法扩展整个系统的架构,来增加服务器的吞吐量和处理能力,以及承载能力。
别的方法先不看了,再细看可以参考,原文链接:https://blog.csdn.net/qishouzhang/article/details/47111945
这个时候就来了
服务器集群
服务器集群就是指将N台服务器集中起来一起进行同一种服务,它们之间通过网络实现通信。让N台服务器之间相互协作,共同承载一个网站的请求压力。
如上图,当用户访问网站时,先到这台前置的响应服务,再最终处理请求的集群中的一台子服务器。
三个臭皮匠,都能对比诸葛亮了,虽然有些夸张,但在这里确实是异曲同工!
在客户端看来就像是只有一个服务器。
专业一点就是:
集群(cluster)它就是一组计算机,它们作为一个整体向用户提供一组网络资源,这些单个的计算机系统就是集群的节点(node)。集群提供了以下关键的特性。
可扩展性。集群的性能不限于单一的服务实体,新的服务实体可以动态的加入到集群,从而增强集群的性能。
高可用性。集群通过服务实体冗余使客户端免于轻易遭遇到“out of service”警告。当一台节点服务器发生故障的时候,这台服务器上所运行的应用程序将在另一节点服务器上被自动接管。
消除单点故障
对于增强数据可用性、可达性和可靠性是非常重要的。
负载均衡。负载均衡能把任务比较均匀的分布到集群环境下的计算和网络资源,以便提高数据吞吐量。
错误恢复。如果集群中的某一台服务器由于故障或者维护需要而无法使用,资源和应用程序将转移到可用的集群节点上。这种由于某个节点中的资源不能工作,另一个可用节点中的资源能够透明的接管并继续完成任务的过程叫做错误恢复。
集群出来了,那什么是分布式呢?
简单说:分布式是指**将不同的业务分布在不同的地方**。 而上述集群指的是将几台服务器集中在一起,实现同一业务。分布式可以认为是通过网络连接多个组件而形成的系统。
广义上说前后分离的应用就能算分布式,前端的 js 代码在浏览器跑着,后端的代码在服务器跑着,两种不同的组件合力对外提供服务构成分布式。
而我们常提到的分布式是狭义上的,指代不同的组件通过协作构成的系统。
而集群常指的同一个组件多实例而构成逻辑上的整体。
这两个概念不冲突,分布式系统里面可以包含集群,像我们的商品服务就可以是集群部署。
为什么要把业务分布到不同的地方呢?在相同地方不是更加容易管理吗?具体的业务都要分在不同的地方是不是太夸张了?
总结有以下几个原因:
我觉得最主要的是考虑到服务器性能的问题。单台服务器的性能毕竟有限,综合利用多个节点的处理能力,才能提高整体的服务能力
分布式模块可以采用不同的解决方案。只要是满足指定的是交互协议,各模块可以根据各自的业务特点,选择不同的处理方式,如微软的解决方案,也可使用J2EE.
模块的内聚性更高,更多的关注自身业务。
分布式系统与集群的关系总结
分布式:不同的业务模块部署在不同的服务器上或者同一个业务模块分拆多个子业务,部署在不同的服务器上,解决高并发的问题
集群:同一个业务部署在多台机器上,提高系统可用性
分布式是指将不同的业务分布在不同的地方。 而集群指的是将几台服务器集中在一起,实现同一业务。
分布式中的每一个节点,都可以做集群。 而集群并不一定就是分布式的。
分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率
RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue 高级消息队列协议 )的开源实现,能够实现【异步消息处理】
RabbitMQ是一个消息代理:它接受和转发消息。
MQ(message queue)
,从字面意思上看,本质是个队列,FIFO 先入先出
只不过队列中存放的内容是 message 而已,还是一种跨进程
的通信机制,用于上下游传递消息
。在互联网架构中,MQ 是一种非常常见的上下游
“逻辑解耦+物理解耦”的消息通信服务。
使用了 MQ 之后,消息发送上游只需要依赖 MQ,不 用依赖其他服务。
“上下游”指:
优缺点
优点:异步消息处理
业务解耦(下订单操作:扣减库存、生成订单、发红包、发短信),
将下单操作主流程:扣减库存、生成订单
然后通过MQ消息队列完成通知,发红包、发短信
错峰流控 (通知量 消息量 订单量大的情况实现MQ消息队列机制,淡季情况下访问量会少)
灵活的路由(Flexible Routing)
在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。
RabbitMQ网站端口号:15672
程序里面实现的端口为:5672
queue队列
Queue(队列)RabbitMQ的作用是存储消息,队列的特性是先进先出。
生产者生产消息最终被送到RabbitMQ的内部对象Queue中去,
而消费者则是从Queue队列中取出数据。
消息队列
消息(Message)是指在应用间传送的数据
。消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象。
消息队列(Message Queue)
是一种应用间的通信方式:
消息队列中间件
kafka rabbitMQ activeMQ rocketMQ(可以处理分布式事务)
干什么用的:
使用rabbitmq 中间件,将一些无需即时返回且耗时的操作提取出来,进行了异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量。
使用场景
在我们秒杀抢购商品的时候,系统会提醒我们稍等排队中,而不是像几年前一样页面卡死或报错给用户。
为什么选择RabbitMQ
1、除了Qpid,RabbitMQ是唯一一个实现了AMQP标准的消息服务器;
2、可靠性,RabbitMQ的持久化支持,保证了消息的稳定性;
3、高并发,RabbitMQ使用了Erlang开发语言,Erlang是为电话交换机开发的语言,天生自带高并发光环,和高可用特性;
4、集群部署简单,正是应为Erlang使得RabbitMQ集群部署变的超级简单;
5、社区活跃度高,根据网上资料来看,RabbitMQ也是首选;
工作机制
生产者、消费者和代理
在了解消息通讯之前首先要了解3个概念:生产者、消费者和代理。
生产者:消息的创建者,负责创建和推送数据到消息服务器;
消费者:消息的接收方,用于处理数据和确认消息;
代理:就是RabbitMQ本身,用于扮演“快递”的角色,本身不生产消息,只是扮演“快递”的角色。
举个例子,如果订单系统最多能处理一万次订单,这个处理能力应付正常时段的下单时绰绰有余,正 常时段我们下单一秒后就能返回结果。
但是在高峰期,如果有两万次下单操作系统是处理不了的,只能限制订单超过一万后不允许用户下单【防止宕机】。使用消息队列做缓冲,我们可以取消这个限制,把一秒内下的订单分散成一段时间来处理,这时有些用户可能在下单十几秒后才能收到下单成功的操作,但是比不能下单的体验要好。
RabbitMQ好处很明显,那它有什么缺点吗?
在访问的过程中,被RabbitMQ排了队,肯定增加了访问过程的时间,对用户有一定的影响,再使用RabbitMQ进行排队
以电商应用为例,应用中有订单系统、库存系统、物流系统、支付系统。
注意:在上述中,它不是不处理,而是暂时缓存,系统恢复之后再继续处理,但是下单是正常成功了的。
有些服务间调用是异步的,例如 :
1.ActiveMQ 优点:
ActiveMQ是一个开源的消息中间件,它实现了JMS(Java消息服务)规范,支持多种协议和编程语言,包括Java、C++、.NET、Web Services等。ActiveMQ提供了丰富的特性和灵活的配置选项,可以满足不同应用场景的需求。
单机吞吐量万级,时效性 ms 级,可用性高,基于主从架构实现高可用性,消息可靠性较 低的概率丢失数据 缺点:官方社区现在对 ActiveMQ 5.x 维护越来越少,高吞吐量场景较少使用。
ActiveMQ的主要特点包括:
支持多种协议:ActiveMQ支持多种协议,包括OpenWire、AMQP、STOMP、MQTT等,可以满足不同应用场景的需求。
多语言支持:ActiveMQ支持多种编程语言,包括Java、C++、.NET、Web Services等,可以方便地在不同的平台上使用。
高可用性:ActiveMQ支持主从复制和集群部署,可以提高系统的可用性和可靠性。
消息持久化:ActiveMQ支持消息的持久化存储,即使发生系统故障也不会丢失消息。
事务支持:ActiveMQ支持JTA(Java事务API)和XA(分布式事务)事务,可以保证消息的完整性和一致性。
Spring集成:ActiveMQ可以方便地集成到Spring框架中,通过Spring的消息容器可以实现异步消息处理。
可扩展性:ActiveMQ提供了灵活的配置选项和插件机制,可以方便地扩展和定制功能。
总的来说,ActiveMQ是一个成熟稳定的消息中间件,可以满足不同应用场景的需求。由于其开源免费和丰富的特性,受到了广泛的应用和认可。
2.Kafka 大数据的杀手锏:
Kafka是由Apache开发的一个分布式的消息队列系统,主要用于处理大数据流。Kafka最初是由LinkedIn开发的,后来成为了Apache的顶级项目之一。Kafka的设计目标是高吞吐量、低延迟、分布式的数据处理系统,可以处理海量的数据。
Kafka的主要特点包括:
高吞吐量:Kafka可以处理海量的数据,具有高吞吐量和低延迟的特点。
分布式架构:Kafka采用分布式架构,可以水平扩展,支持集群部署。
消息持久化:Kafka可以将消息持久化存储到磁盘上,即使发生系统故障也不会丢失消息。
多副本备份:Kafka支持多副本备份,可以提高系统的可靠性和容错性。
可扩展性:Kafka提供了灵活的配置选项和插件机制,可以方便地扩展和定制功能。
支持流处理:Kafka可以与流处理框架(如Apache Storm、Apache Spark)结合使用,实现实时流处理。
开源免费:Kafka是一个开源的项目,可以免费使用和修改,受到了广泛的应用和认可。
Kafka适合于处理海量数据和实时流处理的场景,例如日志收集、实时计算、在线数据分析等。由于其高吞吐量、低延迟和分布式架构等特点,Kafka成为了大数据处理领域的重要工具之一。
谈到大数据领域内的消息传输,则绕不开 Kafka,这款为大数据而生的消息中间件, 以其百万级 TPS 的吞吐量名声大噪,迅速成为大数据领域的宠儿,在数据采集、传输、存储的过程中发挥 着举足轻重的作用。
目前已经被 LinkedIn,Uber, Twitter, Netflix 等大公司所采纳。
优点: 性能卓越,单机写入 TPS 约在百万条/秒,最大的优点,就是吞吐量高。时效性 ms 级可用性非 常高,kafka 是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用,消费者采 用 Pull 方式获取消息, 消息有序, 通过控制能够保证所有消息被消费且仅被消费一次;有优秀的第三方 Kafka Web 管理界面 Kafka-Manager;在日志领域比较成熟,被多家公司和多个开源项目使用;
功能支持: 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用 缺点:Kafka 单机超过 64 个队列/分区,Load 会发生明显的飙高现象,队列越多,load 越高,发送消 息响应时间变长,使用短轮询方式,实时性取决于轮询间隔时间,消费失败不支持重试;支持消息顺序, 但是一台代理宕机后,就会产生消息乱序,社区更新较慢;
3.RocketMQ
RocketMQ是阿里巴巴开发的一个分布式消息中间件系统,它采用了分布式架构,可以处理海量消息的传输和存储。RocketMQ主要解决了高可靠性、高吞吐量、分布式事务等问题。
RocketMQ的主要特点包括:
高可靠性:RocketMQ采用了主从复制、多副本备份等机制,可以保证消息在传输和存储过程中的可靠性。
高吞吐量:RocketMQ采用了分布式架构和多线程处理,可以实现高吞吐量的消息传输和存储。
分布式事务:RocketMQ支持分布式事务,可以保证消息的一致性和完整性。
可扩展性:RocketMQ采用了分布式架构,可以水平扩展,支持集群部署。
多语言支持:RocketMQ支持多种编程语言,包括Java、C++、Python等。
开源免费:RocketMQ是一个开源的项目,可以免费使用和修改,受到了广泛的应用和认可。
也适合于高可靠性、高吞吐量、分布式事务等场景,例如电商交易、金融支付、物流管理等。由于其高可靠性、高吞吐量和分布式事务等特点,RocketMQ成为了企业级消息中间件的重要工具之一。
RocketMQ
出自阿里巴巴的开源产品,用 Java 语言实现,在设计时参考了 Kafka,并做出了自己的一 些改进。被阿里巴巴广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog
分发等场 景。
优点:单机吞吐量十万级,可用性非常高,分布式架构,消息可以做到 0 丢失,MQ
功能较为完善,还是分 布式的,扩展性好,支持 10 亿级别的消息堆积,不会因为堆积导致性能下降,源码是 java
我们可以自己阅 读源码,定制自己公司的 MQ
缺点:支持的客户端语言不多,目前是 java
及 c++,其中 c++不成熟;社区活跃度一般,没有在 MQ
核心中去实现 JMS
等接口,有些系统要迁移需要修改大量代码
4.RabbitMQ
RabbitMQ是一种开源的消息中间件系统,采用Erlang语言开发,支持多种协议和编程语言,如AMQP、STOMP、MQTT、HTTP、WebSocket等。RabbitMQ提供了丰富的特性和灵活的配置选项,可以满足不同应用场景的需求。
RabbitMQ的主要特点包括:
支持多种协议和编程语言:RabbitMQ支持多种协议和编程语言,包括AMQP、STOMP、MQTT、HTTP、WebSocket等,可以满足不同应用场景的需求。
可靠性:RabbitMQ采用了消息确认和持久化等机制,可以保证消息的可靠性和不重复消费。
可扩展性:RabbitMQ采用了分布式架构,可以水平扩展,支持集群部署。
灵活的路由机制:RabbitMQ支持灵活的路由机制,可以根据消息的内容和属性进行路由。
可视化管理界面:RabbitMQ提供了可视化的管理界面,可以方便地管理和监控消息队列。
Spring集成:RabbitMQ可以方便地集成到Spring框架中,通过Spring的消息容器可以实现异步消息处理。
开源免费:RabbitMQ是一个开源的项目,可以免费使用和修改,受到了广泛的应用和认可。
总的来说,RabbitMQ是一个成熟稳定的消息中间件,可以满足不同应用场景的需求。由于其开源免费和丰富的特性,受到了广泛的应用和认可。
2007 年发布,是一个在 AMQP
(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最 主流的消息中间件之一。
优点:由于 erlang
语言的高并发特性,性能较好;吞吐量到万级,MQ
功能比较完备,健壮、稳定、易 用、跨平台、支持多种语言 如:
Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP 等,支持 AJAX 文档齐全;开源提供的管理界面非常棒,用起来很好用,社区活跃度高;
更新频率相当高 https://www.rabbitmq.com/news.html
缺点:商业版需要收费,学习成本较高
选择需考虑的因素
选择合适的消息队列系统需要考虑多个因素,包括应用场景、性能需求、可靠性、可扩展性、开发语言等。
应用场景:不同的消息队列系统适合不同的应用场景。例如,如果你的应用场景需要高可靠性和高吞吐量的消息传输,可以考虑使用RocketMQ或者Kafka;如果你的应用场景需要灵活的路由机制和多种协议支持,可以考虑使用RabbitMQ;如果你的应用场景需要实时的数据处理和交互,可以考虑使用Apache Pulsar或者Redis。
性能需求:消息队列系统的性能对于大规模系统的稳定运行很关键。不同的消息队列系统的性能表现也各不相同。例如,Kafka和RocketMQ都有很好的性能表现,可以支持高并发的消息传输和处理。
可靠性:可靠性是消息队列系统的核心特性之一,对于一些对消息可靠性要求高的应用场景来说,可靠性更是重中之重。RabbitMQ和RocketMQ都采用了消息确认和持久化等机制,可以保证消息的可靠性和不重复消费。
可扩展性:随着业务的发展,对于消息队列系统的扩展性需求也越来越高。不同的消息队列系统的扩展性也各不相同。例如,Kafka和RocketMQ都采用了分布式架构,可以水平扩展,支持集群部署。
开发语言:不同的消息队列系统支持的开发语言也有所不同。例如,RabbitMQ支持多种编程语言,包括Java、C++、Python等;Kafka和RocketMQ主要支持Java语言。
综上所述,选择合适的消息队列系统需要综合考虑多个因素,根据具体的应用场景和需求进行评估和决策。不同的消息队列系统各有特点,需要根据实际情况进行选择和使用。
1.
Kafka
Kafka 主要特点是基于 Pull 的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集 和传输,适合产生大量数据的互联网服务的数据收集业务。
大型公司建议可以选用,如果有日志采集功能, 肯定是首选 kafka 了。
尚硅谷官网 kafka 视频连接 http://www.gulixueyuan.com/course/330/tasks
2.
RocketMQ
天生为金融互联网领域而生,对于可靠性要求很高的场景,尤其是电商里面的订单扣款,以及业务削峰,在大量交易涌入时,后端可能无法及时处理的情况。RoketMQ
在稳定性上可能更值得信赖,这些业务 场景在阿里双 11 已经经历了多次考验,如果你的业务有上述并发场景,建议可以选择 RocketMQ
。
3.
RabbitMQ
结合 erlang
语言本身的并发优势,性能好时效性微秒级,社区活跃度也比较高,管理界面用起来十分 方便,如果你的数据量没有那么大,中小型公司优先选择功能比较完备的 RabbitMQ
。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。