Android应用集成RabbitMQ消息处理指南

Android应用集成RabbitMQ消息处理指南

    • RabbitMQ
    • 1、前言
    • 2、RabbitMQ简介
      • 2.1、什么是RabbitMQ
      • 2.2、RabbitMQ的特点
      • 2.3、RabbitMQ的工作原理
      • 2.4、RabbitMQ中几个重要的概念
    • 3、在Android Studio中集成RabbitMQ
      • 3.1、在Manifest中添加权限:
      • 3.2、在build.gradle(:app)下添加依赖:
    • 4、建立连接
      • 4.1、创建ConnectionFactory对象
      • 4.2、使用ConnectionFactory创建连接
      • 4.3、创建Channel
      • 4.4、声明队列、交换机等
      • 4.5、生产或消费消息
      • 4.6、关闭连接
    • 5、发送消息
      • 5.1、创建连接和通道
      • 5.2、声明队列
      • 5.3、准备消息内容
      • 5.4、发布消息
      • 5.5、关闭资源
      • 5.6、案例
    • 6、接收消息
      • 6.1、创建连接和通道
      • 6.2、声明队列
      • 6.3、定义消费者
      • 6.4、监听队列
      • 6.5、接收消息
      • 6.6、确认消息
      • 6.7、关闭资源
      • 6.8、案例
    • 7、确认机制
      • RabbitMQ中的确认机制主要分为两种:
        • 7.1、发布确认(Publisher Confirms)
        • 7.2、消费者确认(Consumer Acknowledgments)
    • 8、确认主题
      • RabbitMQ有几种常见的主题类型,选择使用哪一种主要根据具体的应用场景:
        • 8.1、Direct exchange(默认)
        • 8.2、Fanout exchange
        • 8.3、Topic exchange
        • 8.4、Headers exchange
      • 选择使用哪种主题类型,主要根据实际的业务需求来判断:
    • 9、使用示例
      • RabbitMQ在Android、IOS、小程序等多端应用中典型应用场景和作用:
        • 9.1、异步处理
        • 9.2、推送通知
        • 9.3、数据传输
        • 9.4、负载均衡
        • 9.5、流量削峰
        • 9.6、服务解耦
        • 9.7、弹性扩容
        • 9.8、离线操作支持
      • 实际应用:
        • 效果展示
        • 具体实现
    • 10、总结

RabbitMQ

RabbitMQ官网直通车 —> ✈✈✈✈✈✈

1、前言

       最近工作繁忙,好久没有更新博文了。

       对于互联网饱和的今天,如何做到不同系统之间传递信息与通信?在实际项目中,多个端例如:ios、android、pc、小程序采用从RabbitMQ上获取实时包消息,然后根据此实时包消息来做响应处理。

       随着互联网技术的发展,系统之间的耦合度越来越高。为了实现系统间的解耦,消息中间件应运而生。其中作为一款优秀的开源消息中间件,RabbitMQ凭借其易用、高可靠、多协议支持等特性,被广泛应用于异步处理、任务队列等领域,成为实际项目的首选。

       但是对于许多人来说,RabbitMQ还是比较陌生的。概念多、不知如何上手使用,这成为很多人学习和使用RabbitMQ的障碍。接下来,给大家介绍关于RabbitMQ的内容。

2、RabbitMQ简介

2.1、什么是RabbitMQ

       MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。其中较为成熟的MQ产品有IBM WEBSPHERE MQ等等。

RabbitMQ是采用Erlang语言实现的开源消息队列系统,是当前最主流的消息中间件之一。

通俗来讲的话,RabbitMQ就像是一个邮局,负责接收和转发信件。

  • 生产者就像邮寄的客户,把信件(消息)投递到RabbitMQ邮局。
  • 消费者就像收信人,从RabbitMQ邮局取走并处理信件。
  • RabbitMQ保证每封信件(消息)都会安全可靠地到达收信人(消费者),它不会丢失或者重复发送信件。
  • RabbitMQ可以给不同的收信人(消费者)分发同一封信件的复印件,这样多个收信人可以并行处理信件。
  • 如果RabbitMQ邮局堆积太多信件来不及处理,它会把信件排队,先进先出依次发送。
  • RabbitMQ还可以给特殊的信件设置优先级,让重要的信件优先处理。
  • RabbitMQ可以根据收信人的处理能力分发信件,不会让一个收信人处理过多信件。

所以简单来说,RabbitMQ就是一个智能的邮局系统,保证每个消息都被安全可靠地发送和处理。它非常适合用于不同系统之间传递消息与通信。

2.2、RabbitMQ的特点

  • 支持多种消息协议,包括STOMP、MQTT等。
  • 支持消息队列,可以缓存消息。
  • 支持消息持久化,防止消息丢失。
  • 支持复杂的路由规则,可以实现发布-订阅、负载均衡等功能。
  • 高可靠性,支持集群模式。
  • 管理界面友好,使用方便。

2.3、RabbitMQ的工作原理

  • 生产者(Publisher)生成消息并发布到RabbitMQ服务器。
  • 消费者(Consumer)从RabbitMQ服务器拉取消息并进行处理。
  • RabbitMQ充当了一个消息代理(Message Broker)的角色,负责接收、存储和转发消息。

2.4、RabbitMQ中几个重要的概念

  • Producer(生产者):发送消息的应用程序是Producer。Producer将消息发布到RabbitMQ中去。
  • Consumer(消费者):接收消息的应用程序是Consumer。Consumer从RabbitMQ中获取消息进行处理。
  • ConnectionFactory(工厂类):它是是RabbitMQ Java客户端用于创建连接的工厂类。它封装了用于创建连接的所有参数配置。
  • Exchange(交换机):交换机用于接收生产者发送的消息,并根据路由键将消息路由到指定的队列中。
  • Queue(消息队列):消息队列是RabbitMQ内部存储消息的缓冲区。Producer发送的消息会先存储在Queue中,Consumer从Queue中获取消息进行处理。
  • Channel(通道):进行消息读写的通道,它是建立在Connection上的一个虚拟连接。为了实现并发,同时方便业务和异常隔离,最佳实践是基于单个Connection建立多个Channel,而不是直接基于Connection操作。
  • Routing Key(路由键):生产者将消息发布到Exchange时,会指定一个Routing Key。Exchange根据这个Routing Key决定将消息路由到哪个队列。
  • Binding(绑定):绑定是Exchange和Queue之间的关联关系。绑定中可以包含routing key。
  • Virtual host(虚拟主机):RabbitMQ可以创建多个虚拟主机,用于进行权限管理和进行逻辑隔离。
  • Message Acknowledgment (消息确认):消费者可以启用消息确认机制,在收到消息并处理后发送确认回执给RabbitMQ,RabbitMQ才会将消息从Queue中移除。

3、在Android Studio中集成RabbitMQ

3.1、在Manifest中添加权限:

<uses-permission android:name="android.permission.INTERNET" />

3.2、在build.gradle(:app)下添加依赖:

implementation 'com.rabbitmq:amqp-client:5.19.0'

耐心等待as同步完成后,就可以使用RabbitMQ的相关api了。

4、建立连接

4.1、创建ConnectionFactory对象

这个对象包含了创建连接需要的配置,比如RabbitMQ主机地址,端口,虚拟主机,用户名密码等。

ConnectionFactory factory = new ConnectionFactory();
// 连接配置
// factory.setHost(Config.MQ_ADDRESS); // 服务器ip
// factory.setPort(Integer.parseInt(Config.MQ_PORT)); // 端口
// factory.setUsername(Config.MQ_USERNAME); // 用户名
// factory.setPassword(Config.MQ_PASSWORD); // 密码
// factory.setVirtualHost(Config.MQ_VIRTUALHOST);
factory.setUri(url);

4.2、使用ConnectionFactory创建连接

调用ConnectionFactory的createConnection()方法可以创建一个连接对象。

Connection connection = factory.newConnection();

4.3、创建Channel

在连接上创建一个通道,用于进行消息发布或者消费。

Channel channel = connection.createChannel();

4.4、声明队列、交换机等

使用channel进行队列、交换机等的声明。

4.5、生产或消费消息

通过channel发送或接收消息。

4.6、关闭连接

使用完成后关闭连接和channel。

channel.close();
connection.close();

5、发送消息

5.1、创建连接和通道

使用ConnectionFactory创建连接,然后在连接上创建通道。

5.2、声明队列

如果队列不存在,需要提前声明队列。

5.3、准备消息内容

定义要发送的消息内容体,可以是字节数组或字符串等。

5.4、发布消息

使用通道对象调用basicPublish方法,它需要exchange名称,routing key和消息内容。

5.5、关闭资源

发送完成后可以关闭通道和连接。

5.6、案例

// 构建消息内容
String message = "Hello World!";

// 发布消息到队列
channel.basicPublish(EXCHANGE_NAME, "routingkey", null, message.getBytes());

// 关闭资源
channel.close();
connection.close();

6、接收消息

6.1、创建连接和通道

使用ConnectionFactory创建连接,然后在连接上创建通道。

6.2、声明队列

如果队列不存在则需要先声明队列。

6.3、定义消费者

实现Consumer接口,定义消息处理逻辑。

6.4、监听队列

使用通道对象调用basicConsume方法,监听指定队列。

6.5、接收消息

RabbitMQ将向Consumer递送消息,在handleDelivery方法中可以获取消息并处理。

6.6、确认消息

处理完成后,调用channel的basicAck方法手动确认消息。

6.7、关闭资源

最后需要关闭通道和连接。

6.8、案例

channel.basicConsume(QUEUE_NAME, true, consumer); 

public class MyConsumer implements Consumer {
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
    // 获取消息并处理
    String message = new String(body, "UTF-8");
    System.out.println("Received message: " + message);
    
    // 确认消息
    channel.basicAck(envelope.getDeliveryTag(), false);
  }
}

7、确认机制

RabbitMQ中的确认机制主要分为两种:

7.1、发布确认(Publisher Confirms)

这是一种单向确认机制,允许生产者知道消息是否被 RabbitMQ 接收。

在 Channel 上启用确认模式后,所有的消息都会被指派一个唯一的 ID(从 1 开始),一旦消息被投递到所有匹配的队列后,RabbitMQ 就会发送一个确认给生产者(包含消息的唯一 ID),这就使得生产者知道消息已经被处理了。

如果消息和队列是可持久化的,那么确认机制本身对消息持久化也是必要的。


在 Java 客户端中,可以通过 Channel 的 confirmSelect 方法将 Channel 设置为确认模式:

channel.confirmSelect();

之后可以添加监听器监听确认和未确认的消息:

channel.addConfirmListener(new ConfirmListener(){
  // ...
});
7.2、消费者确认(Consumer Acknowledgments)

这是一种双向确认机制,不仅可以告诉生产者消息已送达,也可以告诉 RabbitMQ 消息已经被消费者接收并处理完毕。

开启确认模式后,消息一旦被消费者接收,就会从 RabbitMQ 的消息缓冲区中移除。如果消费者在处理消息时发生故障或者异常退出,未处理完毕的消息就会被 RabbitMQ 重新派发给其他消费者,以此来确保消息不会丢失。

通过正确使用确认机制,既可以提高 RabbitMQ 的性能和消息处理能力,也可以确保业务流程的完整性。所以在实际使用中,确认机制是非常重要的。


在 Java 客户端中,可以在 basicConsume 时设置autoAck=false,之后手动调用 basicAck 实现确认:

channel.basicConsume(queue, false, consumer); 

consumer.handleDelivery(envelope, properties, body) {
  //...
  channel.basicAck(envelope.getDeliveryTag(), false); 
}

8、确认主题

RabbitMQ有几种常见的主题类型,选择使用哪一种主要根据具体的应用场景:

8.1、Direct exchange(默认)

直接交换机,按照routing key完全匹配分发消息到队列。场景是需要指定的队列接收消息。

8.2、Fanout exchange

扇出交换机,会将消息分发到所有绑定的队列。场景是需要广播消息。

8.3、Topic exchange

主题交换机,按照routing key的规则匹配分发消息到队列。场景是需要根据规则分发消息到不同队列。

8.4、Headers exchange

头交换机,按照发送消息的headers属性进行匹配分发消息。场景是需要根据消息头进行路由分发。

选择使用哪种主题类型,主要根据实际的业务需求来判断:

  • 如果需要直接将消息发送到指定的队列,使用direct交换机。
  • 如果需要广播消息到所有队列,使用fanout交换机。
  • 如果需要基于规则匹配分发消息,使用topic交换机。
  • 如果需要根据消息头属性进行分发,使用headers交换机。

在代码中,声明交换机时指定类型即可,如下:

channel.exchangeDeclare("myExchange","topic");

9、使用示例

RabbitMQ在Android、IOS、小程序等多端应用中典型应用场景和作用:

9.1、异步处理

各端可以通过RabbitMQ实现任务的异步处理,避免用户等待,提升用户体验。比如小程序下单后,通过RabbitMQ异步把订单信息发送给服务器。

9.2、推送通知

可以通过RabbitMQ实现移动端的消息推送通知,如订单发货通知等。

9.3、数据传输

移动端和服务器端可以通过RabbitMQ进行数据的传输,避免直接耦合,提高传输灵活性。

9.4、负载均衡

RabbitMQ可以在多端和服务器之间进行负载均衡,防止服务器压力过大。

9.5、流量削峰

使用RabbitMQ的消息队列处理请求峰值,防止服务器被瞬时压垮。

9.6、服务解耦

不同端只依赖RabbitMQ进行通信,不需要关注对方技术实现细节,实现服务解耦。

9.7、弹性扩容

通过RabbitMQ可以方便各端与服务器的弹性扩容。

9.8、离线操作支持

移动端可以通过RabbitMQ实现某些离线操作,待网络恢复后再同步到服务器。

实际应用:

       本人在实际物联网项目中,用户通过无线设备测量身体指标后,设备通过网络把数据给到后台;后台通过解析数据后,通过MQ把数据给到每个端,通过收到的信息包各个端做相应的处理。

本人使用ConnectionFactory在创建连接需要配置的时候,通过配置Url来建立连接等。通过startConsumer开始消费并监听指定队列,然后定义回调接口DeliverCallback来接收信息包。最终通过EventBus来传递数据信息包。

效果展示

在这里插入图片描述
在这里插入图片描述

具体实现

在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/473682e32d2a48fabd1efa6bba256e84.png

/**
 * @author 拉莫帅
 * @date 2023/10/24
 * @address
 * @Desc EventBus
 */
public class MessageEvent {
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
/**
 * @author 拉莫帅
 * @date 2023/10/24
 * @address
 * @Desc rabbitMQ
 */
public class RabbitMQUtil {

    private Connection connection;
    private Channel channel;
    private ConnectionFactory factory;
    private String queueName;

    public RabbitMQUtil(String httpType, String userName, String password, String host, String port, String virtualHost, String exChangeName, String bindingKey) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (connection == null) {
                    // 创建一个连接
                    factory = new ConnectionFactory();
                    try {
                        StringBuilder builder = new StringBuilder();
                        StringBuilder stringBuilder = builder.append(httpType).append("://").append(userName).append(":").append(password)
                                .append("@").append(host).append(":").append(port).append("/").append(virtualHost);
                        String url = stringBuilder.toString();
                        Log.e("RabbitMQ", "Url " + url);

                        // 连接配置
                        // factory.setHost(Config.MQ_ADDRESS); // 服务器ip
                        // factory.setPort(Integer.parseInt(Config.MQ_PORT)); // 端口
                        // factory.setUsername(Config.MQ_USERNAME); // 用户名
                        // factory.setPassword(Config.MQ_PASSWORD); // 密码
                        // factory.setVirtualHost(Config.MQ_VIRTUALHOST);
                        factory.setUri(url);

                        // 创建一个新的代理连接
                        connection = factory.newConnection();
                        // 使用内部分配的通道号创建一个新通道
                        channel = connection.createChannel();
                        channel.exchangeDeclare(exChangeName, "topic", true); // 声明一个转发器

                        queueName = channel.queueDeclare().getQueue();
                        channel.queueBind(queueName, exChangeName, bindingKey); // 绑定一个到转发器
                        Log.e("Waiting for logs.", "");

                        startConsumer();
                    } catch (URISyntaxException e) {
                        e.printStackTrace();
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (KeyManagementException e) {
                        e.printStackTrace();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    /**
     * 开始消费
     */
    public void startConsumer() throws Exception {
        Log.e("startConsumer", "");

        // 定义回调接口DeliverCallback
        DeliverCallback callback = (consumerTag, message) -> {
            String result = new String(message.getBody(), "UTF-8");
            Log.e("DeliverCallback >>>", result);

            // 创建一个事件
            MessageEvent event = new MessageEvent();
            event.setMessage(result);

            // 通过EventBus发送事件
            EventBus.getDefault().post(event);
        };

        // 启动基本消费,并传入回调接口
        channel.basicConsume(queueName, true, callback, consumerTag -> {
        });
    }

    /**
     * 关闭连接
     */
    public void close() throws Exception {
        channel.close();
        connection.close();
    }
}
public class MainActivity extends AppCompatActivity {

    private static final String bindingKey = "topic.chain=2.region=3.area=4.pharmacy=5.";

    private RabbitMQUtil rabbitMQUtil;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initMQ();
    }

    private void initMQ() {
        if (rabbitMQUtil == null) {
            rabbitMQUtil = new RabbitMQUtil(Config.MQ_HTTP_TYPE, Config.MQ_USERNAME, Config.MQ_PASSWORD,
                    Config.MQ_ADDRESS, Config.MQ_PORT, Config.MQ_VIRTUALHOST, Config.MQ_EXCHANGE, bindingKey);
        }
    }

    @Override
    public void onStart() {
        super.onStart();

        EventBus.getDefault().register(this);
    }

    @Override
    public void onStop() {
        super.onStop();

        EventBus.getDefault().unregister(this);
    }

    // 接收事件
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessage(MessageEvent event) {
        String message = event.getMessage();
        Log.e("接收MQ +++++++++++++", message);

        // 更新UI
        // ...
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    rabbitMQUtil.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

10、总结

RabbitMQ优秀的性能和灵活性,使其可以处理从简单的请求-响应交互到复杂的异步处理场景

既可以用于系统间的异步解耦,也可以实现应用内不同组件的解耦。它非常适合用于分布式系统之间的数据交换与集成,已成为企业级分布式架构的重要组件之一。

总体来说,RabbitMQ作为一款易用、稳定、功能强大的消息中间件,可以提供高可用、可扩展、低时延的消息服务,在实际项目中使用广泛。并且在当前的技术栈中占有非常重要的地位,是必须要掌握的技能之一。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据中心如何散热?

数据中心的散热是一个非常重要的问题&#xff0c;因为数据中心内运行的服务器、存储设备以及网络设备等都会产生大量的热量&#xff0c;如果不能有效地进行散热&#xff0c;将会导致设备故障和性能下降。下面是一些常见的数据中心散热方法&#xff1a; 空调系统&#xff1a;数据…

Attention is all you need 论文阅读

论文链接 Attention is all you need 0. Abstract 主要序列转导模型基于复杂的循环或卷积神经网络&#xff0c;包括编码器和解码器。性能最好的模型还通过注意力机制连接编码器和解码器提出Transformer&#xff0c;它 完全基于注意力机制&#xff0c;完全不需要递归和卷积对两…

【机器学习】五、贝叶斯分类

我想说&#xff1a;“任何事件都是条件概率。”为什么呢&#xff1f;因为我认为&#xff0c;任何事件的发生都不是完全偶然的&#xff0c;它都会以其他事件的发生为基础。换句话说&#xff0c;条件概率就是在其他事件发生的基础上&#xff0c;某事件发生的概率。 条件概率是朴…

rabbitmq的confirm模式获取correlationData为null解决办法

回调函数confirm中的correlationDatanull // 实现confirm回调,发送到和没发送到exchange,都触发 Override public void confirm(CorrelationData correlationData, boolean ack, String cause) {// 参数说明:// correlationData: 相关数据,可以在发送消息时,进行设置该参数// …

我在Vscode学OpenCV 处理图像

既然我们是面向Python的OpenCV&#xff08;OpenCV for Python&#xff09;那我们就必须要熟悉Numpy这个库&#xff0c;尤其是其中的数组的库&#xff0c;Python是没有数组的&#xff0c;唯有借助他库才有所实现想要的目的。 # 老三样库--事先导入 import numpy as np import c…

Python操作CMD大揭秘!轻松玩转命令行控制

导语&#xff1a; 命令行界面&#xff08;Command Line Interface&#xff0c;简称CLI&#xff09;是计算机操作系统中一种基于文本的用户界面&#xff0c;通过输入命令来与计算机进行交互。Python作为一门强大的编程语言&#xff0c;提供了丰富的库和模块&#xff0c;可以方便…

Android系统Launcher启动流程学习(一)init启动部分

init进程学习&#xff1a; 文件路径system/core/init/init.cpp 解析init.rc配置文件&#xff0c;首先开启ServiceManager和MediaServer等关键进程init进程fork启动Zygote服务进程处理子进程的终止(signal方式)提供属性服务的功能 int main(int argc, char** argv) {//注释一…

机器学习快速入门教程 Scikit-Learn实现

机器学习是什么? 机器学习是一帮计算机科学家想让计算机像人一样思考所研发出来的计算机理论。他们曾经说过,人和计算机其实本没有差别,同样都是一大批互相连接的信息传递和存储元素所组成的系统。所以有了这样的想法,加上他们得天独厚的数学功底,机器学习的前身也就孕育而生…

图像视觉特效处理工具:Boris FX Optics 2024.0.1

BorisFX光效插件Optics首发2024版&#xff1a;3大新功能详解 2023年9月15日&#xff0c;全球领先的视觉后期软件开发公司BorisFX推出了旗下知名软件Boris FX Optics的全新2024版本&#xff0c;这款备受后期处理爱好者喜爱的Photoshop插件和独立程序再次升级&#xff0c;为您的…

致远OA wpsAssistServlet任意文件读取漏洞复现 [附POC]

文章目录 致远OA wpsAssistServlet任意文件读取漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 致远OA wpsAssistServlet任意文件读取漏洞复现 [附POC] 0x01 前言 免责声明&#xff1a;请勿利用…

硬件测试(二):波形质量

一、信号质量测试 信号在传输的过程中&#xff0c;一般不是标准的矩形波信号&#xff0c;信号质量测试即通过示波器测试单板硬件的数字信号和模拟信号的各项指标&#xff0c;包括电源、时钟、复位、CPU小系统、外部接口&#xff08;USB、网口、串口&#xff09;、逻辑芯片(CPLD…

香港金融科技周2023:AIGC重塑金融形态

10月31日&#xff0c;由香港财经事务及库务局与投资推广署主办的“香港金融科技周2023大湾区专场”盛大启幕。中国AI决策领先企业萨摩耶云科技集团创始人、董事长兼 CEO林建明受邀参加圆桌会议&#xff0c;与中国内地、香港以及全球金融科技行业顶尖人才、创新企业、监管机构和…

在前端实现小铃铛上展示消息

点击铃铛显示如下消息框&#xff1a; 如果点击消息&#xff0c;可以实现消息从列表中移除,并从铃铛总数上进行扣减对应的已读消息数。 关于以上功能的实现方式&#xff1a; <!-- 铃铛位置 --><i class"el-icon-bell" click"showPopover true"&…

阿里云OS系统Alibaba Cloud Linux 3系统的安全更新命令

给客户部署的服务&#xff0c;进入运维阶段&#xff0c;但是经常被客户监测到服务器漏洞&#xff0c;现在整理一下&#xff0c;服务器漏洞问题更新命令步骤。 服务器系统&#xff1a; 阿里云linux服务器&#xff1a;Alibaba Cloud Linux 3 漏洞类型和描述&#xff1a; #3214…

K8s Error: ImagePullBackOff 故障排除

Error: ImagePullBackOff 故障排除 1. 起因 起因是要在一组k8s环境下做个Prometheus的测试,当时虚拟机用完直接暂停了. 启动完master和node节点后重启了这些节点. 当检查dashboard时候发现Pod处于ImagePullBackOff状态,使用命令查看详细情况 kubectl describe pods -n kuber…

hadoop配置文件自检查(解决常见报错问题,超级详细!)

本篇文章主要的内容就是检查配置文件&#xff0c;还有一些常见的报错问题解决方法&#xff0c;希望能够帮助到大家。 一、以下是大家可能会遇到的常见问题&#xff1a; 1.是否遗漏了前置准备的相关操作配置&#xff1f; 2.是否遗的将文件夹(Hadoop安装文件夹&#xff0c;/dat…

力控关节性能指标

力控关节是一种用于机器人的关节&#xff0c;具有强大的力控制能力&#xff0c;通常用于执行需要精确力量控制的任务&#xff0c;例如装配、协作操作、力导引操作等。 电机的伺服驱动器通常包括三种控制环——位置环、速度环和电流环。虽然每种控制环的目的是控制电机性能的不同…

无声的世界,精神科用药并结合临床的一些分析及笔记(十)

目录 回 “ 家 ” 克服恐惧 奥沙西泮 除夕 酒与药 警告 离别 回 “ 家 ” 她的锥切手术进行的很顺利&#xff0c;按计划继续返回安定医院调节心理状态&#xff0c;病友们都盼着我们回“家”。当我俩跨入病区&#xff0c;大家都涌过来帮我们大包小包的拎着行李&#xff0…

景联文科技:高质量数据采集清洗标注服务,助力大语言模型红蓝对抗更加精准高效

红蓝对抗是一种测试和评估大语言模型的方法。通过模拟真实世界测试AI模型的潜在漏洞、偏见和弱点&#xff0c;确保大型语言模型的可靠性和性能。 在红蓝对抗过程中&#xff0c;由主题专家组成的专业团队负责模拟攻击和提供反馈&#xff0c;他们试图诱导AI模型产生不当行为&…

【Linux】基本指令-入门级文件操作(三)

目录 基本指令 14 head指令 15 tail指令 管道 16 find指令 17 grep指令 18 zip&#xff06;unzip指令 19 tar指令 20 su指令 总结 基本指令 14 head指令 功能&#xff1a;在屏幕上显示文件的内容&#xff0c;默认显示前10行&#xff0c;如果加上选项-n&#xff0c;则…