RabbitMQ之消息模式简单易懂,超详细分享

前言

上一篇对RabbitMQ的流程和相关的理论进行初步的概述,如果小伙伴之前对消息队列不是很了解,那么在看理论时会有些困惑,这里以消息模式为切入点,结合理论细节和代码实践的方式一起来学习。

正文

常用的模式有Simple、Work、Fanout、Direct、Topic、Headers,可以通过设置交换机类型和配置参数来实现各个模式;接下来就分别进行实操演示吧。

以下演示都是通过管理员的账号进行。其实每种模式其实很大一部分操作都是一样的,所以公共部分不会重复截图说明,不过会针对不同的配置进行说明。

1. 简单模式(Simple)

简单模式顾名思义就是简单,不用配置太多的东西,如下图所示:

033ff07a4e59607a42e09c33c229fb22.png

上图解析:

  • P:表示生产者,负责推送消息;

  • C:表示消费者,负责接收消息;

  • 中间红色部分:代表的是队列(Queue);

小伙伴可能会奇怪,这里没有交换机吗?

其实是有的,上一篇说流程的时候,消息肯定是要通过交换机转发到队列中的,这里没有指定,那是因为用到了默认的交换机,具体看以下演示。

1.1 Web管理界面进行演示

对于Web界面演示来说,只需要将消息能生产、投递、消费即可,我们不用去弄一个生产者和消费者,生产者和消费者都是业务处理逻辑用的,所以通常都是根据业务需求就行实现的;话不多说开始演示吧。

根据上图所示,我们只需要创建一个队列即可,然后就可以进行消息模拟发送和消费了。

44ca22e0a063041a37cd9e0ad135ce3a.png

此时并没有指定交换机绑定,点击队列名看详情中的Bindings,有一个默认的交换机已经和队列进行绑定

c99a1015b0fc2005fd379cab581ca614.png

队列详情页面的说明,在上篇文章中就已经标注了,这里就不再赘述。

有了绑定关系之后,就可以在默认的交换机页面开始模拟转发消息;首先进入Exchanges管理页面,点击默认交换机(AMQP default)进入详情开始发布消息:

f8a69d6b70cf3d287bac864baf182226.png

消息发送成功之后就会在队列界面看到消息情况:

f074fff80473910dd0df43d2d6879f51.png

队列里面有了消息之后,就可以模拟消费者进行消息消费,点击队列名进入详情,可在详情也模拟消费:

962e6fa2afeba093ab2610b1c9fb2952.png

如上所示,简单模式整个消费流程就通过Web页面模拟完了。但在消费消息时,提供了Ack Mode模式(消息确认模式)选择来进行消费,可选择的模式如下:

  • Nack message requeue true:获取消息,但是不会向Server做ack应答确认(即不告诉服务器消息被消费了),消息重新入队。即队列中的消息不会被删除掉;

  • Automatic Ack:获取消息,向Server做应答确认(即会告诉服务器消息被消费了),消息不重新入队,将会从队列中删除;

  • Reject requeue true:拒绝获取消息(即拒绝处理消息),消息重新入队;

  • Reject requeue false:拒绝获取消息(即拒绝处理消息),消息不重新入队,将会被删除;

到这关于简单模式下的界面演示就结束了,其中描述的细节内容是共用的,在其他模式下的操作也类似,后续不做重复说明。

1.2 代码进行演示

这里就用控制台的方式,一步一步的实现。这里需要引入Nuget包:RabbitMQ.Client。生产者的整体代码如下:

36cc736f7de9a020c2979ea5a40f821e.png

接下来就一步一步来调试,看看消息是怎么一步一步发出去的;

  • 创建连接

    刚开始没有任何连接,如下:

    eae5e521a81c7aa3cf503efb2d07ed24.png

    代码继续下一步,连接就有了:

    2a92826dcf540747e594f2ffc7aa05e0.png

    此时就可以理解为网络连接上了,但通道还没有创建出来,如下:

    44a4ea9c77b580adbc00b322aac3c007.png
  • 根据连接创建通道

    通道根据连接进行创建,目的是为了提高传输效率,共用一个连接,不然频繁的创建和销毁连接会占资源,影响性能

    c6f2c5ed1dc77f8aa69a18bcf72e67a4.png
  • 定义队列

    有连接和通道之后理论就可以直接发消息了,但直接通信会相互依赖比较强,达不到解耦合的效果。所以需要定义一个队列将消息存放到里面,客户端想用了自己来消费就行,另外队列还可以达到一定的削峰作用

    a6ccc23247614a00fc4290755c28ed90.png

    创建队列的时候需要传几个参数,分别意思如下:

    参数1:queue, 队列的名称;

    参数2:durable, 队列是否持久化;如果为true,服务器重启之后队列还在,不会被清除;否则就被清掉。

    参数3:exclusive ,是否排他,即是否私有的,如果为true,会对当前队列加锁,其他的通道不能访问,并且连接自动关闭;

    参数4:autoDelete, 是否自动删除,当最后一个消费者断开连接之后是否自动删除消息;

    参数5:arguments, 用来设置队列附加参数,如设置队列的有效期、队列的消息生命周期、消息的最大长度等;

  • 发送消息

    经过以上步骤,就可以发送消息了,如上没有定义交换机,那就是绑定了默认交换机。

    54bacfc1343b419df726d8955c6f2a03.png

    发送时的几个参数意思如下:

    参数1:exchange,交换机,这里没有指定交换机。

    参数2:routingKey,路由key,即指定队列,简单模式下,路由key默认就是队列名

    参数3:basicProperties, 配置其他相关属性

    参数4:body ,需要发送的消息内容

以上的生产者完成了,现在再来一个消费者演示一下消息消费,消费者整体代码如下:

33449b82a2ce883230b815f25fc9475f.png

效果如下:

e4beb2f2ef602f1150c8b80fa18139b5.png

在整个过程中,还是会先建立连接,创建通道,指定队列;不同的是增加对接收数据的处理。

是不是用起来比较简单方便,主要是在复杂项目中,消息队列的作用真的很大。来,接着往下说说其他模式。

2. 工作模式(Work)

工作模式是考虑到多个消费者情况下,消息如何被消费的,主要有两种方案,轮询分发和公平分发;

  • 轮询分发:消费者依次轮着消费消息,直到消息消费完为止,按均分配。

  • 公平分发:根据消费者能力进行分发,即处理快的消费就多,处理慢的就消费就少,能者多劳。

f315697994788a0b9d930faf9ef73d2a.png

上图解析:

  • P:表示生产者,负责推送消息;

  • C1、C2:表示多个消费者,都可以从同一个队列接收消息;

  • 中间红色部分:代表的是队列(Queue);

这两种方式需要多个消费者,在界面不太好模拟,所以就直接上代码演示了。

2.1 轮询分发

在简单模式基础上稍微改动一下代码即可。在生产者中发多条消息出来,然后启用多个消费者就可以进行模拟如下:

生产者代码整体如下:

75dad0594e0957e9ca302f90bd3fe5b6.png

消费者代码整体如下:

2007a98b163750538bb0756c1a15c135.png

两个消费者的代码都是一样,没有变动;两个消费者的都是在消费同一个队列的消息,可以先启动两个消费者,然后在启动生产者,效果如下:

f58081badac87d5a32db8b879180c553.png

由上可见,默认情况下其实采用的是轮询方式。

2.2 公平分发

在实际业务中,有些业务处理比较耗时,有些处理耗时不长,如上案例,假如奇数消息需要处理比较耗时,那么对应的消费者就压力比较大。这种情况可以通过公平分发的方式进行业务处理,处理快点的就多处理点。

如何才能知道消费者处理业务完成呢?消费者处理完成之后主动上报是最好不过的,所以只需要在消费者端将自动确认机制改为手动确认即可,即:业务处理完成之后,手动上报确认状态。

生产者的代码不需要变动,只需要稍微改改消费者代码即可,这里模拟两个不同处理能力的消费者:

  • 消费者1处理一条消息业务需要500毫秒;

  • 消费者2处理一条消息业务需要2秒;

消费者1整体代码如下:

65232c4760351e1c7d36767c26efd695.png

消费者2整体代码如下,主要是模拟时间不一样:

ba52edf8eff4734205a2347c60ec106f.png

先启动两个消费者,再启动生产者,看看消费情况,如下:

9097585694f7288e9fea8d70935f59ce.png

以上演示就是公平分发模式的演示,其中有两个关键的步骤:

  • 设置每次消费的消息条数,可以根据实际业务情况配置,这里设置的是每次取一条。通过 channel.BasicQos进行设置。

  • 将消息确认模式改为自动模式,这样就可以根据实际业务处理情况反馈确认信息,服务器就会将消息处理掉,即删除消息。所以一般在实际业务场景大都会推荐使用手动确认的方式,这样避免业务未处理导致消息就被服务器给清掉的情况。

3. 发布订阅模式(Fanout)

Fanout模式是一种发布订阅模式,是一种广播机制,不需要指定路由Key。这种模式的交换机就会将消息广播到绑定的所有队列上去,只要有消费者订阅对应的队列,就会收到消息。如下图:

d7e2feadf3c23294fc2036ee73b458de.png

上图解析:

  • P:表示生产者,负责推送消息;

  • X:表示交换机,图中表示一个交换机绑定了多个队列;

  • C1、C2:表示多个消费者,都可以从同一个队列接收消息;

  • 中间红色部分:代表的是队列(Queue);

在这种模式下,消息会一次性被多个消费者消费。

3.1 Web管理界面进行演示
  • 先创建一个Fanout模式的交换机;

    fd19212df195661ddb62575e94e15b86.png
  • 创建两个队列(根据实际需要创建多个),并将队列绑定到上一步创建的交换机上;

    这里演示就创建两个队列,分别是FanoutQ1和FanoutQ2

    d536b34638e0b3c9ca0f10ebffeb22bb.png

    在队列详情页或交换机详情页都可以进行交换机和队列的绑定,这里分别在FanoutQ1和FanoutQ2队列详情页进行绑定,如下:

    6d02a81d7ba55c29fa1e8d1b0b4f8ab7.png

    同样的方式绑定FanoutQ2,  绑定完成之后,可以在交换机详情页看到对应的绑定队列:

    4c4cee7201e76b38df1f1ec685b61d55.png
  • 通过交换机上投递消息,看效果;

    此时通过FanoutExchange交换机投递消息,绑定到此交换机上的队列都能收到:

    25d2e9dc9e42ae14f8bf52b0250264ed.png

    查看队列消息情况,可以看到两个队列都接收到消息了。

    d157126b101047555f6a2100ffea323a.png
3.2 代码进行演示

其实代码和操作Web一样,只是用代码实现生产者和消费者而已。

  • 生产者的代码

    71c50c30bfcb8d086c62d10e2d15d662.png

    因为Fanout交换机不用关注RoutingKey,所以在发布消息时,第二个参数不需要传递RoutingKey。

  • 消费者1的代码

    a5922457fb7efa8703730addd30dba41.png

    消费者比较关注的是交换机需要和生产者指定的是同一个,队列和交换机有绑定。

  • 消费者2的代码,其实和消费者1基本一样,只是定义的队列不一样

    f05e3664331d44fd767575ace139b926.png
  • 先启动消费者,然后启动生产者,看效果

    5969cc3303b7cf3d01522abf06666bd8.png

    这里是控制台程序,为了显示方便就先启动消费者,后期的生产者,实际应用场景先启动谁都行。

4. 路由模式(Direct)

Direct模式是在Fanout基础增加RoutingKey条件, 即交换机不会将消息现全部投递到所有队列,而是只投递到对应RoutingKey下的队列。如图:

7323ae25ac3327dca065ca866bbe174a.png

上图解析:

  • P:表示生产者,负责推送消息;

  • X:表示交换机,指定类型为direct,图中表示一个交换机绑定了多个队列;

  • 中间箭头上的error、info、warning代表具体的RoutingKey;

  • C1、C2:表示多个消费者,都可以从同一个队列接收消息;

  • 中间红色部分:代表的是队列(Queue);

Direct模式其实在实际应用场景中用的比较多的,默认的Exhanges也是Direct模式, 很多关于消息队列的框架,默认也是采用这种模式,主要原因是根据RoutingKey精确的处理对应的业务,不会由于考虑不周到,导致消息处理有不确定性,性能相对也不错

4.1 Web管理界面进行演示
  • 先创建一个Direct模式的交换机;

    aa80914afff4868e5f1dd0eb349539b7.png
  • 创建两个队列,然后将队列绑定到上一步创建的交换机上,并指定对应的RoutingKey;

    bbf61adc76109b3b29464ca8896c2288.png

    创建队列完成之后,还需要绑定到交换机上,上一种模式演示的是从队列详情中维护绑定关系,这次从交换机详情中进行演示,如下:

    绑定第1个队列,指定RoutingKey是order,模拟处理订单的:

    81e10f660d5e5270f3a598e363e3b8cf.png

    绑定第2个队列,指定RoutingKey是msg,模拟处理消息的:

    e3477cc8dcff045476d4827dc8429d50.png

    有了绑定关系,就可以测试验证了。

    注:这里的RoutingKey可以根据实际情况随意指定的。

  • 向交换机上投递消息,看效果;

    模拟发布一个RoutingKey为order的消息:

    c94d0936216e4b90087a333e78742f01.png

    再发布一个消息,指定RoutingKey为msg,如下:

    85a2e01f0a0e2c3871fc3892a2ebab39.png

    两个消息都发布成功,而是指定对应的RoutingKey进行投递,所以现在绑定到此交换机上两个队列中分别有一条数据,查看队列的消息概况:

    e4fed63511a2611cdafe5a6e1c373f84.png

    可以进入队列详情,通过GetMessage获取到具体的消息内容,这里就不截图了,上面已经演示过。

4.2 代码进行演示

在Fanout的代码基础上稍微改动即可,主要改动点就是改变交换机的类型,并在队列和交换机绑定时设置对应的RoutingKey,发布消息的时候指定交换机和RoutingKey。

  • 生产者代码

    4b6b7b93ac901d2f4610e6625d58a552.png
  • 消费者1代码,主要是绑定队列时指定的RoutingKey为order

    5605ddbc472f31c43970c269e8adc5a5.png
  • 消费者2代码,主要是绑定队列时指定的RoutingKey为msg

    535d21bdf38cb6e32b345a4ae5433972.png
  • 运行起来看效果:

    0e9ebda8df824d7b9f55b814790a71ac.png

    如上演示效果,和Web演示一样,只有精确匹配到RoutingKey才能消费到对应的消息数据。

5. 主题模式(Topic)

Topic模式是在Direct模式基础增加模糊匹配RoutingKey,Direct精确匹配RoutingKey,Topic可以通*或#进行模糊匹配,从而把消息投递到对应的队列中,如图:

a0157308e88c7a74fda372c97c241a32.png

上图解析:

  • P:表示生产者,负责推送消息;

  • X:表示交换机,指定类型为topic,图中表示一个交换机绑定了多个队列;

  • 中间箭头上的文字代表模糊匹配的RoutingKey;其中*表示匹配RoutingKey中的一个词,#号表示匹配RoutingKey的零个或多个词,匹配符需要与点号(.)搭配使用。*.orange.test.# 示例中orange算一个词,test算一个词,即通过点号(.)分开的就称为一个词。

  • C1、C2:表示多个消费者,都可以从同一个队列接收消息;

  • 中间红色部分:代表的是队列(Queue);

5.1 Web管理界面进行演示
  • 先创建一个Topic模式的交换机;

    e26db81684394a48739324371856dd55.png
  • 创建两个队列,然后将队列绑定到上一步创建的交换机上,并指定对应的RoutingKey;

    eb9a3218904c4d014f605fa96944510c.png

    将队列绑定到交换机上,这里还是在交换机详情中进行演示,如下:

    30cb02bdbda35698b4c5a3fefe619899.png

    同样的步骤分别对TopicQ1和TopicQ2进行规则绑定,如下:

    现在的TopicExchange的绑定关系如下:

    80e635701402e57dd020e472fc70be65.png

    有了关系之后就可以进行验证效果了。

  • 向交换机上投递消息,会根据RoutingKey的模糊匹配规则将消息投递到对应的队列中,看效果;

    先指定order.create.test发布消息,看看会匹配哪些队列:

    45459595564e4b77073763ee5b72a413.png

    TopicQ2接收到消息,匹配到路由规则order.#

    b5552438f50a3127d66fe7dad06f5125.png

    再指定RoutingKey 为order.update 发布一个消息,如下:

    c4ed784985cb5c2ebef1f0a79cc190a8.png

    TopicQ1和TopicQ2都收到消息了,匹配到路由规则order.#和order.*,如下:

    84fe33e22efe55b536334337fb1ef1ba.png

    再指定RoutingKey 为order发布一个消息,就会匹配到order.#,这里就不截图了。

    以上测试说明:在Topic类型交换机和队列绑定关系时,可以指定RoutingKey的匹配规则,星号、#号、点号搭配使用,其中*表示匹配RoutingKey中的一个词,#号表示匹配RoutingKey的零个或多个词

    更多情况,小伙伴们自己动手试试。

5.2 代码进行演示

在Direct的代码基础上稍微改动即可,主要改动点就是改变交换机的类型,并在队列和交换机绑定时设置对应的RoutingKey,这里的RoutingKey是一个规则,是星号、#号、点号和每个词的组合,发布消息的时候指定交换机和RoutingKey,RoutingKey会去匹配绑定的规则。

  • 生产者代码

    d028210c62d4c4b762c524d7d227b1ac.png
  • 消费者1代码,指定路由匹配规则为order.#

    8aaf1b360be5a0f7d89db634756d518a.png
  • 消费者2代码,指定路由匹配规则为order.*

    589fcd6da1f4b6fd65a10861bffc3bce.png
  • 演示效果,将生产者和消费者都启动

    5672762b0e7222defa1ffac88ec73c9d.png

    如上图,和Web演示一样,#号匹配0个和多个词,*号只能匹配一个词。 符号可以与词任意组合,小伙伴可以根据业务情况自行发挥。

6. 参数模式(Headers)

Headers模式不是通过RoutingKey进行匹配投递消息,而是匹配请求头中所带的键值进行消息投递,所以创建队列是需要设置绑定的头部信息,有两种模式:全部匹配和部分匹配。

  • 全部匹配:x-match=all,表示所有的键值都匹配了才行。

  • 部分匹配:x-match=any,表示只要其中有键值对匹配就行。

5.1 Web管理界面进行演示
  • 先创建一个Headers模式的交换机;

    96f3f692bcc3a5755a670e9a4781707d.png
  • 创建两个队列,然后将队列绑定到上一步创建的交换机上,可以指定Headers的参数;

    e712a42d5d19da2dd3698588ab0dd10c.png

    将队列绑定到交换机上,这里还是在交换机详情中进行演示,如下:

    这里不使用RoutingKey的方式,而是通过设置参数的形式进行绑定,后续投递消息的时候就匹配参数,如果能匹配上,就将消息投递到对应的队列。

    绑定HeaderQ1队列:

    c305952d4a35a3d6431d299240a11c6f.png

    同样的方式绑定HeaderQ2队列,只是只添加了一个键值对,order:111,最后HeaderExchange交换机的绑定关系如下:

    1f51b1b1fe7ff222f601e44f5c248194.png

    关系绑定好之后就可以进行测试效果了。

  • 向交换机上投递消息,会根据检查Headers参数的条件是否符合,若符合将消息投递到对应的队列中,看效果;

    设置两个参数进行发布,如下:

    0a6070d304b036a5607e1df7dd2dba32.png

    可以看到两个队列都匹配到了,因为order和msg键值对匹配到HeaderQ1,order的键值对匹配到HeaderQ2,如果只设置一个order简直对呢:

    5f1c5aeb5e9ec7f991843cf406edaedd.png

    此时只有HeaderQ2才能精确匹配,HeaderQ1没有全部匹配,所以对应队列没有收到消息,如下:

    d36993b3636b9d1fc28fc8507f6c9435.png

    由此可见,在界面上没有指定x-match绑定的话,默认是all,就是要全部匹配才投递消息到对应队列

    这里继续新增一个HeaderQ3的队列,创建方式和上面不一样,只是在绑定交换机的时候增加x-match 为 any,如下:

    f8d603a6a1b7cf11c6454b8447e294d5.png

    绑定成功之后,现在关系如下,其中order的键值对是在每个绑定中都有,如下:

    af02aecfa6229cfbb672efa2eb5cf473.png

    测试发消息之前,把之前消息都清空了,也就是队列中的消息都是空的,这次我们再指定order为111的参数进行发布消息,看看有哪些队列收到消息呢:

    586622d5e248a9f60c3802cecf6d9fed.png

    消息发出后,之后HeaderQ2和HeaderQ3收到消息,HeaderQ2只有一个order参数,精确匹配上了,HeaderQ3有多个参数,但设置了x-match为any,所以只要匹配其中一个即可。HeaderQ1多个参数需要全部匹配才行,所以没有接收到消息:

    158f3d9a4d503ab8cffe3a2f51e0e84c.png
5.2 代码进行演示

Headers模式是根据参数进行匹配,不是通过RoutingKey,所以只需要在绑定队列时设置好参数,在发送消息的时候也设置好参数,这样就会根据匹配原则去匹配参数,如果匹配上,消息就投递到对应的队列,供消费者进行消费。这里为了演示比较清晰一点,使用一个生产者,三个消费者的形式进行演示。

  • 生产者

    43111006641c06af31d9dcd36241a9ff.png

    代码中关键的部分是指定交换机的类型为Headers,然后模拟了两类参数的形式投递消息,方便用于测试参数匹配模式的测试。

  • 消费者1,绑定参数为order:111和msg:222

    2e6ce8f0cb2983998c0f9b8d94bb2020.png
  • 消费者2,和消费者1代表基本一样,只是绑定参数不一样;

    72c7b49a25485bf9afaaafb04f0e537e.png
  • 消费者3,代表基本和消费者1一样,只是在参数指定的时候增加了x-match来指定匹配模式,这里指定为any,也就是只要其中有部分匹配上也可以消费到消息。

    ee4b91dfe7be7b442751aec7d2f41ed2.png
  • 演示效果,启动生产者和消费者:

    73028409ab248ab369cc9037dcc8eeb6.png

    如上图,消费者3指定了匹配模式为部分匹配,所以可以接收到一个参数的消息,而消费者1需要精确匹配,所以不能接收到。

关于常用的消息模式就聊到这吧,小伙伴们可以根据自己的业务场景进行使用,相关演示代码的地址如下:

码云:https://gitee.com/CodeZoe/dot-net-core-study-demo/tree/main/RabbitMQDemo

总结

RabbitMQ提供了多种模式应对各种业务,但匹配条件越是模糊或者参数化,那性能相对比较弱。再回顾一些常用的消息队列组件,是不是很多都是默认使用Direct模式,精确匹配的RoutingKey可以针对具体不同业务处理,匹配性能也相对比较高;当然其他模式小伙伴也可以针对业务情况进行使用。

后续的文章将继续分享RabbitMQ消息确认机制、死信队列、磁盘监控等相关知识点的应用,关注“Code综艺圈”,和我一起学习吧。

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

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

相关文章

每天一个linux命令(6):rmdir 命令

今天学习一下linux中命令: rmdir命令。rmdir是常用的命令,该命令的功能是删除空目录,一个目录被删除之前必须是空的。(注意,rm - r dir命令可代替rmdir,但是有很大危险性。)删除某目录时也必须具…

jvm系列(八):jvm知识点总览

在江湖中要练就绝世武功必须内外兼备,精妙的招式和深厚的内功,武功的基础是内功。对于武功低(就像江南七怪)的人,招式更重要,因为他们不能靠内功直接去伤人,只能靠招式,利刃上优势来…

计算机基础知识的文献,四 计算机文献检索基础知识(原理、结构和功能)

1.计算机检索原理计算机一方面接受用户的检索提问,一方面从数据库中读取文献记录,然后把两者进行比较,即检索提问标识与文献记录标识进行匹配运算,如果比较的结果一致,那么这篇文献就会作为命中文献在检索结果中显示&a…

APP地推心得:可复制的APP地推方案

APP地推难?APP地推方案包含哪些?现在,不需要编程就能自己完成手机APP制作,而且还有大量的APP模板,可以直接套用。APP的制作资金技术大幅度降低,现在最大的问题就是怎么APP推广的问题。 在移动互联网的时代&…

【代码笔记】iOS-播放从网络上下载的语音

代码&#xff1a; ViewController.m #import "ViewController.h" //录音 #import <AVFoundation/AVFoundation.h>interface ViewController () {//播放器AVAudioPlayer *player; }endimplementation ViewController- (void)viewDidLoad {[super viewDidLoad];/…

C# 基于.NET6的CM+Fody+HC入门实战项目(经典)

概述上期我们概述了CMFodyHC&#xff0c;如果之前没有阅读&#xff0c;可以先了解下&#xff1a;C# 为什么说CMFodyHC是WPF开发的最强组合&#xff1f;今天基于最新的VS版本、最新的CM框架版本&#xff0c;.NET基于6.0&#xff0c;搭建了一个WPF入门学习项目实例&#xff0c;关…

PHP资源列表(转)

一个PHP资源列表&#xff0c;内容包括&#xff1a;库、框架、模板、安全、代码分析、日志、第三方库、配置工具、Web 工具、书籍、电子书、经典博文等等。 初始翻译信息来自&#xff1a;《推荐&#xff01;国外程序员整理的 PHP 资源大全》 该内容也可以在github的相关项目上浏…

当今 计算机已进入千家万户英语,学生英语教学论文,关于信息技术在大学英语教学中的应用探析相关参考文献资料-免费论文范文...

导读:这是一篇与学生英语教学论文范文相关的免费优秀学术论文范文资料,为你的论文写作提供参考。摘 要&#xff1a;随着经济全球化和信息化时代的到来,计算机技术已深入到社会的各个领域.以往大学中所使用的传统面授课教学模式已经跟不上信息时代的发展步伐,不能满足当今教学的…

POJ - 2187 Beauty Contest(最远点对)

http://poj.org/problem?id2187 题意 给n个坐标&#xff0c;求最远点对的距离平方值。 分析 模板题&#xff0c;旋转卡壳求求两点间距离平方的最大值。 #include<iostream> #include<cmath> #include<cstring> #include<queue> #include<vector>…

Kong入门学习实践(2)实验环境搭建

【API网关】| 总结/Edison Zhou最近在学习Kong网关&#xff0c;因此根据老习惯&#xff0c;我会将我的学习过程记录下来&#xff0c;一来体系化整理&#xff0c;二来作为笔记供将来翻看。由于我司会直接使用Kong企业版&#xff0c;学习过程中我会使用Kong开源版。本篇&#xff…

Mysql-索引的基础和类型

一、 索引的基础 索引类似于书籍的目录&#xff0c;要想找到一本书的某个特定主题&#xff0c;需要先查找书的目录&#xff0c;定位对应的页码。 存储引擎使用类似的方式进行数据查询&#xff0c;先去索引当中找到对应的值&#xff0c;然后根据匹配的索引找到对应的数据行 二…

ligerUI的列头合并代码片段

//列头合并 function onAfterShowData(data){//显示数据前触发此事件 console.log(123); var k 0; var tr $(.l-grid-body.l-grid-body1).find(table tr);//找到被冻结的列&#xff08;frozen&#xff09;,利用find方法找到所有的行 $.each($(tr)…

我的未来计算机作文,我的未来作文(精选4篇)

我的未来作文(精选4篇)在平平淡淡的日常中&#xff0c;大家总免不了要接触或使用作文吧&#xff0c;作文根据体裁的不同可以分为记叙文、说明文、应用文、议论文。怎么写作文才能避免踩雷呢&#xff1f;以下是小编收集整理的我的未来作文&#xff0c;仅供参考&#xff0c;大家一…

RDS for MySQL Mysqldump常见问题及处理

2019独角兽企业重金招聘Python工程师标准>>> 摘要&#xff1a; RDS for MySQL Mysqldump 常见问题和处理 GTID 特性相关 避免表级锁等待 设置导出字符集 其他导出时需要注意的选项 举例 RDS for MySQL 不支持的选项 RDS for MySQL 逻辑备份 1. GTID 特性相关 MySQ…

AI求解PDE

一、波动方程的PINN解法: Guo Y, Cao X, Liu B, et al. Solving partial differential equations using deep learning and physical constraints[J]. Applied Sciences, 2020, 10(17): 5917. 二、二维的Navier–Stokes方程组的PINN解法 矢量形式的不可压缩Navier-Stokes方程…

使用CADisplayLink实现UILabel动画特效

在开发时&#xff0c;我们有时候会遇到需要定时对UIView进行重绘的需求&#xff0c;进而让view产生不同的动画效果。 本文项目 效果图 初探 CADisplayLink 定时对View进行定时重绘可能会第一时间想到使用NSTimer&#xff0c;但是这样的动画实现起来是不流畅的&#xff0c;因为在…

《ASP.NET Core 6框架揭秘》实例演示[27]:ASP.NET Core 6 Minimal API的模拟实现

Minimal API仅仅是在基于IHost/IHostBuilder的服务承载系统上作了小小的封装而已&#xff0c;它利用WebApplication和WebApplicationBuilder这两个类型提供了更加简洁的API&#xff0c;同时提供了与现有API的兼容。[本文节选《ASP.NET Core 6框架揭秘》第17章]一、基础模型二、…

Mysql的关联查询语句

一 内连接( inner join&#xff09; 1、多表中同时符合某种条件的数据记录的集合 (取两表公共部分) 2、inner join 可以缩写成 join 例如: select * from A,B WHERE A.idB.id 或者 select * from A inner join B on A.idB.id 内连接分为三类:{ &#xff08;1&#xff0…

高性能Server---Reactor模型

无处不在的C/S架构 在这个充斥着云的时代,我们使用的软件可以说99%都是C/S架构的&#xff01; 你发邮件用的Outlook,Foxmail等你看视频用的优酷&#xff0c;土豆等你写文档用的Office365,googleDoc&#xff0c;Evernote等你浏览网页用的IE,Chrome等(B/S是特殊的C/S)……C/S架构…

计算机控制系统的试题,计算机控制系统练习题(1)

21. 给出多通道复用一个D/A转换器的原理示意图。 答&#xff1a;22. 什么是信号重构&#xff1f;答&#xff1a;把离散信号变为连续信号的过程&#xff0c;称为信号重构&#xff0c;它是采样的逆过程。23. 写出零阶保持器的传递函数&#xff0c;引入零阶保持器对系统开环传递函…