Twisted reactor.listenTCP intermittently cannot connect properly - sockets

I'm running a TCP server on linux using reactor.listenTCP.
All works well for hours (or days), then something happens and clients can connect but they are immediately disconnected by the server.
There is nothing in my protocol implementation that commands a disconnect.
There is nothing in the client implementations that would cause such a disconnect.
The server intermittently sends some data to all users that it finds in the user list using sendLine(data).
I'm wondering if I am meant to perform some operation when a client disconnects that I've missed amd this is causing socket issues.
class MsgHandler(Protocol):
def __init__(self, factory):
self.factory = factory
def connectionMade(self):
self.factory.users.append(self)
def connectionLost(self, reason):
self.factory.users.remove(self)
def dataReceived(self, data):
pass
class outputTcpServerFactory(Factory):
def __init__(self, users):
self.users = users
def buildProtocol(self, addr):
return MsgHandler(self)
class Mainloop(object):
def __init__(self):
self.users = []
s = reactor.listenTCP(port, outputTcpServerFactory(self.users))
reactor.run()
---> Elsewhere in the mainLoop class is code that periodically runs:
for client in self.users:
client.sendLine(data)

You should always enable logging so that you can see unhandled exceptions that the application encounters. These usually make it obvious why something is broken.

Related

mqtt not publishing data onto the broker when qos set to 2

client.publish("topic", payload,qos=2) not publishing data onto the broker whereas the same is working for qos=0 and 1.I have not defined persistence, it is set to default value.
import paho.mqtt.publish as publish
import paho.mqtt.client as mqtt
from random import *
import time
MQTT_IP='192.168.0.23'
MQTT_PORT=1883
global client
import datetime
def on_connect(client, userdata, flags, rc,qos):
if rc==0:
print("MQTT CONNECTION ESTABLISHED")
print(str(client)+'\n'+str(userdata))
def on_message(client, userdata, msg):
print("Message arrived from "+str(client))
print(msg.topic+" "+str(msg.payload))
def MQTT_CONNECTION():
global client
global MQTT_CLIENT_CONNECTED
try:
print("IN mqtt connection")
client = mqtt.Client()
client.connect(MQTT_IP,MQTT_PORT)
client.on_connect = on_connect
client.on_message = on_message
MQTT_CLIENT_CONNECTED=True
except Exception as error:
print("ERROR IN MQTT CONNECTION",error)
MQTT_CLIENT_CONNECTED=False
def publish():
global client
client.publish("1/MB/EM/3/21/IB",2,qos=2,retain=True)
if __name__=="__main__":
MQTT_CONNECTION()
publish()
I have removed all other functionality, for you all to understand better.
You need to start the MQTT client network loop. This is to handle the multi step handshake for QOS 2 messaging.
The python Paho client has 3 ways to run the loop.
You can start the loop on a background thread by calling client.loop_start()
You can start the loop on the current thread, which will then block forever with client.loop_forever()
You can run the tasks that the loop perform within your own loop by calling client.loop() at regular intervals
Which one you choose depends on what else your code is doing, but I suspect that starting the loop on a background thread is probably the best.

Akka remoting: Remote subscribed event listener custom serialising a Watch message

I have the following remote actor set up.
actorSystem.actorSelection(remoteConfig.getString("/myEventListener")).resolveOne().map{ar =>
actorSystem.eventStream.subscribe(ar, classOf[MyEvent])
}
I also have my own custom serialization. The issue is that this gets sent a Watch message which has the following signature:
private[akka] final case class Watch(watchee: InternalActorRef, watcher: InternalActorRef) extends SystemMessage
Which is not so straight forward to serialize. Any suggestions on how to proceed on this one? Sending a remote message with references to InternalActorRef seems a bit of an odd one.
And to note I use other remote actors directly (not as event listeners), these dont get sent the Watch message:
val emailService = actorSystem.actorSelection(remoteConfig.getString("/emailCommandHandler"))

Akka: send error from routee back to caller

In my project, I created UserRepositoryActor which create their own router with 10 UserRepositoryWorkerActor instances as routee, see hierarchy below:
As you see, if any error occur while fetching data from database, it will occur at worker.
Once I want to fetch user from database, I send message to UserRepositoryActor with this command:
val resultFuture = userRepository ? FindUserById(1)
and I set 10 seconds for timeout.
In case of network connection has problem, UserRepositoryWorkerActor immediately get ConnectionException from underlying database driver and then (what I think) router will restart current worker and send FindUserById(1) command to other worker that available and resultFuture will get AskTimeoutException after 10 seconds passed. Then some time later, once connection back to normal, UserRepositoryWorkerActor successfully fetch data from database and then try to send result back to the caller and found that resultFuture was timed out.
I want to propagate error from UserRepositoryWorkerActor up to the caller immediately after exception occur, so that will prevent resultFuture to wait for 10 seconds and stop UserRepositoryWorkerActor to try to fetch data again and again.
How can I do that?
By the way, if you have any suggestions to my current design, please suggest me. I'm very new to Akka.
Your assumption about Router resending the message is wrong. Router has already passed the message to routee and it doesnt have it any more.
As far as ConnectionException is concerned, you could wrap in a scala.util.Try and send response to sender(). Something like,
Try(SomeDAO.getSomeObjectById(id)) match {
case Success(s) => sender() ! s
case Failure(e) => sender() ! e
}
You design looks correct. Having a router allows you to distribute work and also to limit number of concurrent workers accessing the database.
Option 1
You can make your router watch its children and act accordingly when they are terminated. For example (taken from here):
import akka.routing.{ ActorRefRoutee, RoundRobinRoutingLogic, Router }
class Master extends Actor {
var router = {
val routees = Vector.fill(5) {
val r = context.actorOf(Props[Worker])
context watch r
ActorRefRoutee(r)
}
Router(RoundRobinRoutingLogic(), routees)
}
def receive = {
case w: Work =>
router.route(w, sender())
case Terminated(a) =>
router = router.removeRoutee(a)
val r = context.actorOf(Props[Worker])
context watch r
router = router.addRoutee(r)
}
}
In your case you can send some sort of a failed message from the repository actor to the client. Repository actor can maintain a map of worker ref to request id to know which request failed when worker terminates. It can also record the time between the start of the request and actor termination to decide whether it's worth retrying it with another worker.
Option 2
Simply catch all non-fatal exceptions in your worker actor and reply with appropriate success/failed messages. This is much simpler but you might still want to restart the worker to make sure it's in a good state.
p.s. Router will not restart failed workers, neither it will try to resend messages to them by default. You can take a look at supervisor strategy and Option 1 above on how to achieve that.

Spray.io log leaks sensitive information

I'm using Spray client to consume a third-party API. Unfortunately, the API I'm consuming is not very secure and utilizes an authentication method using GET query parameters.
Sometimes we're getting timeouts or connection issues which we know to deal with applicatively. The problem is that Spray logs this at a WARN log-level, and the URL including the sensitive query parameters () are being written in our log files.
Here's an example of the log file.
2015-05-19 12:23:17,024 WARN HttpHostConnectionSlot - Connection attempt to 10.10.10.10:443 failed in response to GET request to /api/?type=keygen&user=test_user&password=S3kret! with 2 retries left, retrying...
2015-05-19 12:23:17,084 WARN HttpHostConnectionSlot - Connection attempt to 10.10.10.10:443 failed in response to GET request to /api/?type=keygen&user=test_user&password=S3kret! with 1 retries left, retrying...
Is there any way to filter this? (Maybe in Akka?)
Spray reuses akka-logging for doing all logging groundwork.
In akka you can redeclare a custom event logger in application config:
akka {
# event-handlers = ["akka.event.Logging$DefaultLogger"] // default one
event-handlers = ["com.example.PrivacyLogger"] // custom one
# Options: ERROR, WARNING, INFO, DEBUG
loglevel = "DEBUG"
}
It may look like this:
class PrivacyLogger extends DefaultLogger {
override def receive: Receive = {
case InitializeLogger(_) ⇒ sender() ! LoggerInitialized
case event: LogEvent ⇒ print(stripSecret(event))
}
private def stripSecret(event:LogEvent) = ...
}
But you always can implement your own message processing logic here instead of simple printing.
PS. If you use slf4j for logging, the solution will mostly look the same, but with some minor differences like overriding akka.event.slf4j.Slf4jEventHandler instead of DefaultLogger.

Why do I get 'Handshake timed out'? How can I configure timeout period?

I am new in Akka actors and I am doing some tests. Suppose I have actors performing long running tasks like following:
override def receive = {
case email: Email => /*Future*/ {
Thread sleep 3000
}
}
I ran a stress test (remote actos on another machine in network) and I receive the following error:
akka.remote.EndpointAssociationException: Association failed with [akka.tcp://EmailSystem#192.168.1.6:5000]
Caused by: akka.remote.transport.AkkaProtocolException: No response from remote. Handshake timed out
How can I configure this to don't get this error again? Should I use a future in the receive method instead of normal code (as on comment above)? What is the impact of doing that?
It's a really bad idea to have an actor that blocks for a long time like that, since it cannot respond to messages and additionally the akka default threadpool is one thread per core of your computer so you might also be stopping other actors from processing any messages.
Fork that blocking job on a separate execution context/thread pool instead (and make sure to limit how many threads there is in that threadpool). You can then notify the actor using pipeTo:
import akka.pattern.pipe
case email: Email =>
val futureEmail = Future {
... send email and then ...
EmailSent()
}
futureEmail pipeTo sender