RabbieMQ使用(Product)
这次体现到消息队列强大到解耦性,我的product是c#客户端,consumer是java的jar包
1.Nuget安装rabbitmq.client
2.自己准备了一个product的代码,一直用的这个
public class RabbitMQClientHandler
{
public static string UserName = "UserName ";
public static string PassWord = "PassWord ";
public static string IpAddress = "rabbitmqurl";
public static int Port = Port ;
/// <summary>
/// RabbitMQ队列上传动作
/// </summary>
// 定义一个静态变量来保存类的实例
private static RabbitMQClientHandler uniqueInstance;
//定义一个标识确保线程同步
private static readonly object locker = new object();
/*-------------------------------------------------------------------------------------*/
//ConnectionFactory
private static ConnectionFactory mc_ConnectionFactory = null;
//Connection
public IConnection Connection;
//Channel
public IModel Channel;
/*-------------------------------------------------------------------------------------*/
/// <summary>
/// 定义私有构造函数,使外界不能创建该类实例
/// </summary>
public RabbitMQClientHandler()
{
//连接工厂
mc_ConnectionFactory = new ConnectionFactory();
//连接工厂信息
mc_ConnectionFactory.HostName = IpAddress;
mc_ConnectionFactory.Port = Port;
mc_ConnectionFactory.UserName = UserName;
mc_ConnectionFactory.Password = PassWord;
//创建连接
Connection = mc_ConnectionFactory.CreateConnection();
//创建频道
Channel = Connection.CreateModel();
}
/// <summary>
/// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
/// </summary>
/// <returns></returns>
public static RabbitMQClientHandler GetInstance()
{
// 当第一个线程运行到这里时,此时会对locker对象 "加锁",
// 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
// lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
// 双重锁定只需要一句判断就可以了
if (uniqueInstance == null)
{
lock (locker)
{
// 如果类的实例不存在则创建,否则直接返回
if (uniqueInstance == null)
{
uniqueInstance = new RabbitMQClientHandler();
}
}
}
return uniqueInstance;
}
/*-------------------------------------------------------------------------------------*/
/// <summary>
/// 发送消息至服务端
/// </summary>
/// <param name="ExchangeName">交换机名称</param>
/// <param name="queueName">Queue名称</param>
/// <param name="RoutingKey">RoutingKey</param>
/// <param name="message">需要发送的消息</param>
/// <returns></returns>
public bool publishMessageToServer(string ExchangeName, string queueName, string RoutingKey, string message)
{
try
{
//创建一个持久化的频道
bool durable = true;
Channel.QueueDeclare(queueName, durable, false, false, null);
//设置消息持久性
//var properties = Channel.CreateBasicProperties();
//properties.SetPersistent(true);
//消息内容转码,并发送至服务器
var messageBody = Encoding.UTF8.GetBytes(message);
Channel.BasicPublish(ExchangeName, RoutingKey, null, messageBody);
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
}
在使用前,初始化一次该类,然后直接调用GetInstance()方法,便可获得RabbitMQClientHandler,之后再调用publishMessageToServer方法,便可向队列写入消息。
小插曲
因为在使用过程中,客户端重启后会丢失已经发送的消息,所以需要获取某个队列的所有消息,通过查看rabbitmq的api文档,找到路径为
/api/queues/vhost/name/get
完整路径为
http://UserName:PassWord@IpAddress:Port/api/queues/vhost/name/get
//vhost 为/的情况下,写作%2F
//name 为queue名称
通过rabbitmq可视化界面,F12,可以查询到该接口为post,需要5个参数
{“ count”:5,“ ackmode”:“ ack_requeue_true”,“ encoding”:“ auto”,“ truncate”:50000}
count:获取的最大消息数,如果队列少于该数量,返回所有的
ackmode:确定是否从队列中删除消息。一般为ack_requeue_true,如果为false的话,获取到消息后,会将消息从队列删除
encoding:必须为auto
truncate:它会把大于给定的大小(以字节为单位)的消息截断,该参数是可选,可传可不传
然后通过post方法调用api会报Error Type 405的错
经过大半天的查询,添加了消息验证和用户代理
string code = Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", username, password)));
//添加Authorization到HTTP头
req.Headers.Add("authorization", "Basic " + code);
req.UserAgent = "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)";
结果又报Error Type 401,再经过大半天的查询解决,最终将.Net Framework3.5升级至4.5,代码没变,竟然出结果了,哭笑不得。