I would write a crapload of shell scripts to start every component locally, in the foreground. Hopefully you can just pass flags to specify ports, rather than having to specify config files. (Though you can easily generate config files from shell scripts)
I use tmux, so I can have all servers up in the foreground and logging to stdout. You can arrange the windows so it's easy to get a global view.
Identify which servers are stateful and which are stateless. For the stateful ones, it's nice to be able to save and restore their state (hopefully just with cp and mv).
Then I would write some more shell scripts to poke at every port. For REST services, just use curl, and possibly some JSON/XML helpers. Stateless servers should be testable exhaustively.
Then pick some code change you want to make. Write the shell snippets to tickle that code path.
Then write some more shell scripts to rebuild every component binary from source. Make your code change, build, restart, and then test to see if it works. Look at the logs for clues.
This is basically the "dynamic" approach to debugging systems, rather than the "static" approach of staring at code. Sometimes staring at code is the right thing to do, but if as you say the sheer volume of code is too much, then figuring out the behavior as a black box -- tickling it with shell scripts -- is often a faster way to understand the system.
They should be scripts because you need to be able to repeat this process many times.
Other strategies are:
- Understand the architecture from the build system. Don't look at the source code, look at how it's compiled. What libraries go in what binaries is a strong indicator of their function.
- Understand the architecture from the deployment. In this case I'm suggesting to rewrite the deployment yourself with shell scripts (to a single host, your dev box). But you can also try to just look at whatever the ops/devops team does to bring up the service in a new cluster.
- Look at any existing system tests / regression tests.