Rabbitmq实现js、python、java 消息互联
Rabbitmq简介
RabbitMQ是基于AMQP实现的一个开源消息组件,主要用于在分布式系统中存储转发消息,由因高性能、高可用以及高扩展而出名的 Erlang 写成。其中,AMQP(Advanced Message Queuing Protocol,即高级消息队列协议),是一个异步消息传递所使用的应用层协议规范,为面向消息的中间件设计。RabbiMQ是EDA事件驱动架构的核心,也是CQRS同步数据的关键。
Rabbitmq特点
高可靠:RabbitMQ 提供了多种多样的特性让你在可靠性和性能之间做出权衡,包括持久化、发送应答、发布确认以及高可用性。
**高可用队列:**支持跨机器集群,支持队列安全镜像备份,消息的生产者与消费者不论哪一方出现问题,均不会影响消息的正常发出与接收。
**灵活的路由:**所有的消息都会通过路由器转发到各个消息队列中,RabbitMQ内建了几个常用的路由器,并且可以通过路由器的组合以及自定义路由器插件来完成复杂的路由功能。
支持多客户端:对主流开发语言(如:Python、Ruby、.NET、Java、C、PHP、ActionScript等)都有客户端实现。
集群:本地网络内的多个Server可以聚合在一起,共同组成一个逻辑上的broker。
**扩展性:**支持负载均衡,动态增减服务器简单方便。
权限管理:灵活的用户角色权限管理,Virtual Host是权限控制的最小粒度。
插件系统:支持各种丰富的插件扩展,同时也支持自定义插件,其中最常用的插件是web管理工具rabbitmq_management。
前期准备
软件 | 版本 |
---|---|
idea | 2021.3 |
pycharm | 2021.1.1 |
vscode | 23.2 |
rabbitmq | 3.8.16 |
情景一:用Rabbitmq实现js,java,python消息互联,达成前后端情感分析功能
实现流程图:
流程一 :js发送消息到python 端于Java端
//引入amqplib模块(需要先使用 npm installl ampqlib 命令进行安装)
var amqp = require('amqplib/callback_api');
//连接localhost(本机ip)或者远程服务端的ip
amqp.connect('amqp://localhost', function(error0, connection) {
if (error0) {
throw error0; //如果与虚拟主机的连接异常抛出错误
}
connection.createChannel(function(error1, channel) {
if (error1) {
throw error1; //创建通道失败,抛出错误
}
var exchange = 'js_logs';
var msg = process.argv.slice(2).join(' ') || 'scyper start';
// asserExchange 实现 assertExchange(交易所名字,模型类型,durable:(true/flase))
channel.assertExchange(exchange, 'fanout', {
durable: false
});
//发送消息 exchange为交易所名字
//piblish功能 (exchange——name,message)
channel.publish(exchange, '', Buffer.from(msg));
console.log(" [x] Sent %s", msg);
});
//关闭通道于连接
setTimeout(function() {
connection.close();
process.exit(0);
}, 500);
});
流程二:java接受消息,开始爬取数据
依赖包的引入
<dependencies>
<!--Rabbitmq依赖包-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--引入rabbotmq依赖-->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.7.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<!--爬虫依赖包-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<!--测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<!--操作文件-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<!--操作字符串-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.3</version>
</dependency>
<!--Jsoup-->
<!-- https://mvnrepository.com/artifact/junit/junit -->
<!--测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<!--操作文件-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- HttpClient -->
<!--Jsoup-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.3</version>
</dependency>
<!--工具包-->
<!--SpringMVC-->
<!--MySQL连接包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- HttpClient -->
<!--Jsoup-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160810</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
java接受接受者 comsumer.java程序
import rab_tool.rabbitUtills;
import java.io.IOException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class recipient {
//封装包函数
//静态函数 类加载执行,提高效率
private static ConnectionFactory conntionFactory;
static {
conntionFactory=new ConnectionFactory();
//类加载的时候执行
conntionFactory.setHost("localhost");
//设置端口
conntionFactory.setPort(5672);
conntionFactory.setVirtualHost("/");
//设置访问虚拟主机的账号,连接虚拟主机
conntionFactory.setUsername("guest");
conntionFactory.setPassword("guest");
//获取连接对象
}
public static Connection getConection(){
try{
//创建连接
//ConnectionFactory conntionFactory=new ConnectionFactory();
//设置主机
return conntionFactory.newConnection();
}catch(Exception e){
System.out.println(e);
e.printStackTrace();
}
return null;
}
//关闭通道
public static void closeconnectionChannel(Channel channel,Connection conn){
try{
if (channel==null)
{
channel.close();
}
if (conn!=null){
conn.close();}
}
catch(Exception e){
e.printStackTrace();
}
}
public String comsumer(){
Connection connect=getConection(); //创建连接
Channel channel =connect.createChannel();//创建通道连接Rabbirmq
//通道绑定交换机
//exchangeDeclare(exchnage——name,model(模型选择)//类型应与对应的生产者模型相同)
channel.exchangeDeclare("js-java","fanout");
//临时对列
String queueName=channel.queueDeclare().getQueue() ;
//绑定交换机和队列
channel.queueBind(queueName,"js_logs","");
//消费消息
channel.basicConsume(queueName,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者1="+new String(body));
msg=body;
}
});
return msg;
}
public void worker_java_to_python(String[] args) throws Exception
{
Connection connection = getConection();
Channel channel = connection.createChannel();
//第一个参数为交换机的名字 第二个为类型 路由模式
String exchange_name="dirst";
//发送的消息
ArrayList<String> messeage=args;
//路由名字的定制 设置routkey可以实现指定目标的传输
String routkey="infor";
channel.exchangeDeclare(exchange_name,"direct");
//发送消息
for(i:meseage){
channel.basicPublish(exchange_name,routkey, null, i);
}
///关闭
rabbitUtills.closeconnectionChannel(channel,connection);
}
public static void main(String arg[])throws Exception{
String flag=comsumer();
ArrayList<String> meg
if(flag=="true")
{
for(int i=0;i<5;i++)
{
Thread.sleep(1 * 1000); //没一秒间隔进行一次
ArrayList<String> meg= get_comment(i*20);
meg_all.add(meg);
System.out.print(meg);
}
//传送数据到python
worker_java_to_python(mse_all)
}
}
}
python接受数据实现情感分析
msseage=[]
#接受信息函数
def direct_messeage(msg):
#绑定对应的主机名 默认是“/”
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
#定义交换机名字 以及 exchange——type
channel.exchange_declare(exchange='dirst',exchange_type='direct')
#消息是否是持续化 持续化指明数据将会保存在硬盘中,不会随着rabbitmq的关闭而关闭
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue
severities ="infor"
if not severities:
sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
sys.exit(1)
for severity in severities:
channel.queue_bind(exchange='dirst',
queue=queue_name,
routing_key=severity)
print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] %r:%r" % (method.routing_key, body))
messeage.append(body)
//绑定方法和队列名
channel.basic_consume(callback,
queue=queue_name,
no_ack=True)
channel.start_consuming()
========================================================================
def get_emotion( data): # 情感分析
# 定义百度API情感分析的token值和URL值
token = '24.6ad6c340d7bdf1f80daed09939755f13.2592000.1619177800.282335-23582305'
url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/sentiment_classify?charset=UTF-8&access_token={}'.format(token)
# 百度情感分析API的上限是2048字节,因此判断文章字节数小于2048,则直接调用
if (len(data.encode()) < 2048):
new_each = {
'text': data # 将文本数据保存在变量new_each中,data的数据类型为string
}
new_each = json.dumps(new_each)
res = requests.post(url, data=new_each) # 利用URL请求百度情感分析API
# print("content: ", res.content)
res_text = res.text # 保存分析得到的结果,以string格式保存
result = res_text.find('items') # 查找得到的结果中是否有items这一项
positive = 1
if (result != -1): # 如果结果不等于-1,则说明存在items这一项
json_data = json.loads(res.text)
negative = (json_data['items'][0]['negative_prob']) # 得到消极指数值
positive = (json_data['items'][0]['positive_prob']) # 得到积极指数值
print("positive:",positive)
print("negative:",negative)
# print(positive)
if (positive > negative): # 如果积极大于消极,则返回2
return 2
elif (positive == negative): # 如果消极等于积极,则返回1
return 1
else:
return 0 # 否则,返回0
else:
return 1
else:
data = cut_text(data, 1500) # 如果文章字节长度大于1500,则切分
# print(data)
sum_positive = 0.0 # 定义积极指数值总合
sum_negative = 0.0 # 定义消极指数值总和
for each in data: # 遍历每一段文字
# print(each)
new_each = {
'text': each # 将文本数据保存在变量new_each中
}
new_each = json.dumps(new_each)
res = requests.post(url, data=new_each) # 利用URL请求百度情感分析API
# print("content: ", res.content)
res_text = res.text # 保存分析得到的结果,以string格式保存
result = res_text.find('items') # 查找得到的结果中是否有items这一项
if (result != -1):
json_data = json.loads(res.text) # 如果结果不等于-1,则说明存在items这一项
positive = (json_data['items'][0]['positive_prob']) # 得到积极指数值
negative = (json_data['items'][0]['negative_prob']) # 得到消极指数值
sum_positive = sum_positive + positive # 积极指数值加和
sum_negative = sum_negative + negative # 消极指数值加和
# print(positive)
print(sum_positive)
print(sum_negative)
if (sum_positive > sum_negative): # 如果积极大于消极,则返回2
return 2
elif (sum_positive == sum_negative): # 如果消极等于于积极,则返回1
return 1
else:
return 0 # 否则,返回0
====================================
消息传送给js
#发送分析结果给js
def worker():
import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='pytho_js',
type='direct')
severity = sys.argv[1] if len(sys.argv) > 2 else 'info'
message = ' '.join(sys.argv[2:]) or 'Hello World!'
channel.basic_publish(exchange='direct_logs',
routing_key=severity,
body=message)
print(" [x] Sent %r:%r" % (severity, message))
connection.close()
if __name__=="__main__":
direct_messeage()
sorce=[]
for i in messeage:
sorce.append(get_emotion(i))
for i in sorce:
worker(i)
流程四 js接收数据
//引入amqplib模块(需要先使用 npm installl ampqlib 命令进行安装)
var amqp = require('amqplib/callback_api');
//连接localhost(本机ip)或者远程服务端的ip
amqp.connect('amqp://localhost', function(error0, connection) {
if (error0) {
throw error0; //如果与虚拟主机的连接异常抛出错误
}
connection.createChannel(function(error1, channel) {
if (error1) {
throw error1; //创建通道失败,抛出错误
}
var exchange = 'python_js';
var msg = process.argv.slice(2).join(' ') || 'Hello World!';
// asserExchange 实现 assertExchange(交易所名字,模型类型,durable:(true/flase))
channel.assertExchange(exchange, 'fanout', {
durable: false
});
//发送消息 exchange为交易所名字
//piblish功能 (exchange——name,message)
channel.publish(exchange, '', Buffer.from(msg));
console.log(" [x] Sent %s", msg);
});
//关闭通道于连接
setTimeout(function() {
connection.close();
process.exit(0);
}, 500);
});
``
**上述流程实现的是基本的数据传输功能,用到了rabbitmq的fanout
模式,direct模式,后续会推出其他模式的运用。**