I would argue that job management is unrelated to messaging, at least according my loose definition of a task that:
* Has a well-defined lifetime — unstarted, running, paused, completed successfully, or failed;
* Is executed from some kind of parameterized "job specification" that describes its inputs and desired behavior;
* Has state data (e.g., completion % progress, log output, metrics, transactional continutation state for pausing/retrying);
* Can be scheduled on multiple nodes;
* Can be created and scheduled multiple times;
* Can be scheduled by priority;
* Can have its resources (RAM, CPU, I/O) constrained.
The thing is, queues are terrible at this. People continue to abuse messaging systems as a scheduler, and it always sucks.
For example, consider acking: For a long-running tasks that might take hours, do you really want to hold up the broker's internal lock for all that time? What if you restart the broker — the task is still running, now you decoupled its running state from the queue. Similarly, queues are terrible at finding out what's waiting, or what has happened. By using the queue as job state, you are coupling scheduling with execution, which is just wrong.
A queue (one that supports priorities, mind you) is, however, excellent for management commands: "Start job X", "pause job X" and so on. But you will want to maintain execution state separately from the queue. A relational database is quite good at this, though one could use a NoSQL databases, too. First, create a row representing the job: {id="job1", state="new", type="import_stuff", params="..."}. Then push a queue message {commmand="start_job", job_id="job1"}. Run a queue consumer or ten on each node. Each consumer acks the message, finds the job in the table and starts it. One could run it as a child process, or in a Docker container. One could of course use an orchestration service (like Mesos/Marathon) to run it, and monitor the service for container events and update the job table appropriately.
I would want to take it further and allow the job to update itself through API, so that it could publish metrics and log messages, as well as maintain whatever data is useful snapshotting. For example, a long-running task to import data into a database would benefit from maintaining a cursor so that you could pause/kill the job and later resume it at the point where it was.