I have a question / problem about Persistent Session and Queuing Messages.
Here is the scenario:
I have a publisher (java server) which is publish message and I have a receiver (android client). When android client it online it gets the messages which amazing, working very well.
However, when I kill the android app and keep sending message from server and when I open android app, android does not receive previous messages.
Server side:
final Mqtt5BlockingClient client = MqttClient.builder()
.useMqttVersion5()
.serverHost(host)
.serverPort(8883)
.sslWithDefaultConfig()
.buildBlocking();
// connect to HiveMQ Cloud with TLS and username/pw
client.connectWith()
.simpleAuth()
.username(username)
.password(UTF_8.encode(password))
.applySimpleAuth()
.noSessionExpiry()
.cleanStart(false)
.send();
// This code is running every 15 sec
String now = LocalDateTime.now().toString();
String message = String.format("Hello: %s", now);
// publish a message to the topic "my/test/topic"
client.publishWith()
.topic("hasan-device/sayHello")
.payload(UTF_8.encode(message))
.retain(true)
.qos(MqttQos.AT_LEAST_ONCE)
.noMessageExpiry()
.send();
Client side:
// create an MQTT client
final Mqtt5BlockingClient client = MqttClient.builder()
.identifier("my-device-1")
.useMqttVersion5()
.serverHost(host)
.serverPort(8883)
.sslWithDefaultConfig()
.automaticReconnectWithDefaultConfig()
.buildBlocking();
// connect to HiveMQ Cloud with TLS and username/pw
client.connectWith()
.simpleAuth()
.username(username)
.password(UTF_8.encode(password))
.applySimpleAuth()
.noSessionExpiry()
.cleanStart(false)
.send();
// subscribe to the topic "my/test/topic"
client.subscribeWith()
.topicFilter("hasan-device/sayHello")
.retainHandling(Mqtt5RetainHandling.SEND)
.send();
// set a callback that is called when a message is received (using the async API style)
client.toAsync().publishes(ALL, publish -> {
byte[] message = publish.getPayloadAsBytes();
LOGGER.info("Received message: {} -> {}, ", publish.getTopic(), new String(message, UTF_8));
});
Expecting to message arrive when device back to online
When the Android app restarts with the persistent session, brokers will send down pending messages immediately. This can happen before the application callbacks get initialised.
Here is an example from when I did some testing with this:
To fix, move this bit of code to execute just before the connectWith call:
// set a callback that is called when a message is received (using the async API style)
client.toAsync().publishes(ALL, publish -> {
byte[] message = publish.getPayloadAsBytes();
LOGGER.info("Received message: {} -> {}, ", publish.getTopic(), new String(message, UTF_8));
});
Related
I am using c# M2MQTT Client code to publish and subscribe the data. I have set the QOS Level 1 or 2. Do not know that how the publisher will get the notification when delivery completes. I have searched a lot on inter net but no code available. Please let me know if any one how to handle the acknowledgement at publisher end in c#.
MqttClient client = new MqttClient(IPAddress.Parse(mqttserverurl));
clientId = Guid.NewGuid().ToString();
client.Connect(clientId, uname, pwd);`enter code here`
client.Publish("testtopic", Encoding.UTF8.GetBytes("Hi"), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, false);
You don't.
It's all handled internally by the MQTT client library and M2MQTT doesn't seem to have a on_publish callback.
I am looking to retrieve some Solace queue stats e.g. the current messages spooled count out of the maximum limit for us to set a threshold to stop publishing more messages to the queue.
Also, to subscribe to vpn events to track message discard rates.
By the time we receive errors e.g. MaxMsgUsageExceeded/SpoolOverQuota, it will be too late.
I can't seem to find any of these on SolaceSystems.Solclient.Messaging API
https://docs.solace.com/API-Developer-Online-Ref-Documentation/net/html/7f10bcf6-19f4-beff-0768-ced843e35168.htm
Would be great if someone could help
(using C# for this)
To poll for Solace queue stats from your C# application, you could use legacy SEMP over the message bus to make a SEMP request for the details that you want. Semp (Solace Element Management Protocol) is a request/reply protocol that uses an XML schema to identify all managed objects available in a message broker. Applications can use SEMP to manage and monitor a message broker.
To allow for legacy SEMP to be used over the message bus, as opposed to the management interface, it first needs to be enabled on the Solace PubSub+ message broker at the VPN level.
To publish a SEMP request with the Solace .Net Messaging API, perform the following steps:
Create a Session.
Create the message topic. “#SEMP//SHOW”
ITopic topic = ContextFactory.Instance.CreateTopic( “#SEMP/<router name>/SHOW”);
Create a request message and set its Destination to the topic in Step 2:
IMessage requestMsg = ContextFactory.Instance.CreateMessage();
requestMsg.Destination = topic;
Set the SEMP request string as the binary attachment.
string SOLTR_VERSION = "8_4_0" //change to the message-broker's version
string SEMP_SHOW_QUEUE = "<rpc semp-version=\"soltr/" + SOLTR_VERSION +
"<show><queue><name>queueName</name><detail></detail></queue></show></rpc>";
requestMsg.BinaryAttachment = Encoding.UTF8.GetBytes(SEMP_SHOW_QUEUE);
Call the SendRequest(…) method on Session.
IMessage replyMsg;
ReturnCode rc = session.SendRequest(requestMsg, out replyMsg, timeout);
The SEMP response is returned in replyMsg.
Obtain the binary attachment data from the reply message:
replyMsg.BinaryAttachment
The binary attachment contains the SEMP reply for the command topic in the publish request.
The Solace PubSub+ message broker does raise an event when an egress message is discarded. However, it is only sent out approximately once every 60 seconds for the specified client so it is not possible to get these exact rates.
It is possible for your .NET application to subscribe to VPN-level events over the message-bus. To do this, you must first enable the Solace PubSub+ message broker to publish the events. You can then subscribe to the special topic and receive the events as messages.
The topic to subscribe to is:
#LOG/<level>/VPN/<routerName>/<eventName>/<vpnName>
The different levels can use the * wildcard. For example, if you wish to subscribe to all VPN events of all levels for the VPN apple on router QA-NY1, the topic string would be:
#LOG/*/VPN/QA-NY1/*/apple
SEMP (starting in v2) is a RESTful API for configuring, monitoring, and administering a Solace PubSub+ broker.
1-The swapper page link is SEMP V2 API
2-The Swagger metadata definitions URL is located # http://{solace-sever-url}/SEMP/v2/config/spec
3- From Visual studio, add REST API Client
4-In the configuration dialog pass swagger metadata URL (defined at step 2), for code purpose I choose SolaceSemp as input value parameter for client namespace input.
4 Once you click ok, VS will create the client along with the models under SolaceSemp namespace
5 Start using the client as per following
using SolaceSemp;
using Microsoft.Rest;
var credentials = new BasicAuthenticationCredentials();
credentials.UserName = "place user name";
credentials.Password = "place password";
using (var client = new SolaceSempClient(credentials))
{
var model = client.GetAboutApi();
}
I am trying not to get the offline messages my scenario is if client1 is offline and client2 is sending messages so client1 should not receive any old messages when he reconnects and he should receive messages sent after reconnection. I am using mqtt library(npm) on client side and mosquitto server. I have tried {clean:true} and publish and subscribe using {qos:0} and its not working.This is my code
client2:
this.client = mqtt.connect(url, {
clean: true
}
this.client.publish("mqtt/location", JSON.stringify(data1) ,{qos: 0});
Client1:
this.client = mqtt.connect(url, {
clean: true
}
this.client.subscribe("mqtt/location", {qos: 0});
this.client.on("message", function(topic, payload) {
console.log(payload);
})
Thanks
If you are setting clean session to true, then the only other explanation is that the messages you are receiving were published with the retained bit set. There is nothing you can do to stop your client receiving those messages, but you can detect them. Any published message that you receive from the broker that has the retained bit set is "old".
I install kafka on a standalone server and try to stream data to mongodb.
when start kafka service, bin/kafka-server-start.sh config/server.properties
I had a warning:
WARN Attempting to send response via channel for which there is no open connection, connection id 0 (kafka.network.Processor)
Even though, there is no problem for data entered at producer and displayed at consumer.
but I think this cause the data write to mongodb. I have no data write to mongodb after start data streaming.
anyone can help with this issue? Thank you so much.
//processor.sendResponse
protected[network] def sendResponse(response: RequestChannel.Response) {
trace(s"Socket server received response to send, registering for write and sending data: $response")
val channel = selector.channel(response.responseSend.destination)
// `channel` can be null if the selector closed the connection because it was idle for too long
if (channel == null) {
warn(s"Attempting to send response via channel for which there is no open connection, connection id $id")
response.request.updateRequestMetrics()
}
else {
selector.send(response.responseSend)
inflightResponses += (response.request.connectionId -> response)
}
so, channel was closed by the selector because it was idle too long
The requirement in our project is, Web UI(MVC 5) will place a request to adapter(intermediate layer) which takes 3-4mins to process the request and computes response. This response needs to be pushed back to UI. We are planning to implement Signalr for posting back the response to UI. I did a small POC on SignalR to open connection and to call a method from javascript and get response back. how can I push the data from server to client(once connection is set), no call from javascript/Web for requesting the response?.
To push datas from the server to the client the basic usage is :
On the client side :
var myHub = $.connection.CustomHub;
myHub.client.myFunction= function (param) {
alert(param);
};
On the server side :
Clients.All.myFunction("parameter");
To find more infos about signalr take a look here :
http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr
You can download the light chat project in the page it's a good start.
Get Hubcontext of the application
IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext('HubName');
On top of hubcontext can broadcast message to all the clients or groups or to specific client based on connection Id
hubContext.Clients.Client(connectionId).JavaScript function(data)