HelloWorld: Finish up BASH how to guide

This commit is contained in:
Ryan Newton 2018-12-12 15:58:08 -08:00
Родитель e154c5e343
Коммит 27b2f88ab5
7 изменённых файлов: 206 добавлений и 98 удалений

Просмотреть файл

@ -25,12 +25,22 @@ namespace Client1
protected override async Task<bool> OnFirstStart()
{
_server = GetProxy<IServerProxy>(_serverName);
_server.ReceiveMessageFork("Hello World 1!");
Console.WriteLine("Press any key to continue");
_server.ReceiveMessageFork("\n!! Client: Hello World 1!");
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\n!! Client: Press any key to continue");
Console.ResetColor();
Console.ReadKey();
_server.ReceiveMessageFork("Hello World 2!");
_server.ReceiveMessageFork("Hello World 3!");
Console.WriteLine("Press any key to end");
_server.ReceiveMessageFork("\n!! Client: Hello World 2!");
_server.ReceiveMessageFork("\n!! Client: Hello World 3!");
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\n!! Client: Press any key to end");
Console.ResetColor();
Console.ReadKey();
Program.finishedTokenQ.Enqueue(0);
return true;

Просмотреть файл

@ -18,31 +18,54 @@ Now you have binaries built under the paths `Server/publish`,
`Client1/publish`, and `Client2/publish`. The two clients are
*different* examples, and only one or the other should be run at a time.
Running
-------
Registering
-----------
### Super quickstart for the impatient
If you're feeling lucky, you can try running the setting
AZURE_STORAGE_CONN_STRING and then running two communicating services
locally in one terminal like so:
./run_helloworld_both.sh
Or you can tease it apart and open the client and server separately,
in separate terminal windows:
./run_helloworld_client.sh
./run_helloworld_server.sh
After you run, you'll want to cleanup the logs (`ambrosia_logs/`)
before running again, or the system will think it's recovering from a
failure and still part of the previous run.
### Longer version
In order to develop your own AMBROSIA services we'll need to walk
through the steps in a bit more detail. There are three main steps.
#### (Steps 1/3) Registering
Before we can run the client/server, we need to register metadata
about these AMBROSIA instances with in the cloud table storage. Pick
a name for your client and server instances.
Ambrosia RegisterInstance -i myclient --rp 2000 --sp 2001 -l ./logs
Ambrosia RegisterInstance -i myserver --rp 2000 --sp 2001 -l ./logs
Ambrosia RegisterInstance -i myclient --rp 1000 --sp 1001 -l ./ambrosia_logs
Ambrosia RegisterInstance -i myserver --rp 2000 --sp 2001 -l ./ambrosia_logs
We've told AMBROSIA that it will use `./logs` for storing logs locally,
but in a production environment of course logs would need to be on a
remotely-mounted file system that is durable even when the machine fails.
We've told AMBROSIA that it will use `./ambrosia_logs` for storing
logs locally, but in a production environment of course logs would
need to be on a remotely-mounted file system that is durable even when
the machine fails.
Running
-------
#### (Step 2/3) Running an instance.
First let's run the server. Open a terminal, and let's set up some of
the configuration information that will be used by the
`runAmbrosiaService.sh` script to launch your process.
export AMBROSIA_INSTANCE_NAME=myclient
export AMBROSIA_IMMORTALCOORDINATOR_PORT=1500
export AMBROSIA_INSTANCE_NAME=myserver
export AMBROSIA_IMMORTALCOORDINATOR_PORT=2500
export AZURE_STORAGE_CONN_STRING=...
To launch a service we're going to use a convenience script called
@ -50,12 +73,34 @@ To launch a service we're going to use a convenience script called
of AMBROSIA. This handles starting the immortal coordinator and
monitorying its health.
runAmbrosiaService.sh
runAmbrosiaService.sh dotnet Server/publish/Server.dll myserver
You could start ImmortalCoordinator yourself, as well, by using two
separate terminals to run:
You'll see a lot of output, with output from the coordinator tagged
`[ImmortalCoord]`. Eventually, the coordinator reports "Ready" and
Alternatively, you could start ImmortalCoordinator yourself, by using
two separate terminals to run:
Cleanup
-------
ImmortalCoordinator -i myserver -p 2500
dotnet Server/publish/Server.dll myserver
#### Running another instance.
Now you have the server running, but for this to be interesting, we
need another client to connect to the server.
export AMBROSIA_INSTANCE_NAME=myclient
export AMBROSIA_IMMORTALCOORDINATOR_PORT=1500
export AZURE_STORAGE_CONN_STRING=...
runAmbrosiaService.sh dotnet Client1/Publish/Client1.dll myclient myserver
#### (Step 3/3) Cleanup
To delete all the metadata we left in the cloud, run the following:
UnsafeDeregisterInstance myclient
UnsafeDeregisterInstance myserver
Note this is called "unsafe" because one must take great care to not
call it while any part of the service may still be running.

Просмотреть файл

@ -21,7 +21,10 @@ namespace Server
public async Task<int> ReceiveMessageAsync(string message)
{
Console.WriteLine("Received message from a client: " + message);
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("\n!! SERVER Received message from a client: " + message);
Console.ResetColor();
_messagesReceived++;
return _messagesReceived;
}

Просмотреть файл

@ -15,18 +15,6 @@ set -euo pipefail
# ------------------------------------------------------------------------------
cd `dirname $0`
# PORTOFFSET: A number to add to all ports to avoid colliding or
# reusing recently used ports.
# if ! [ ${OFFSET:+defined} ]; then
# OFFSET=0
# fi
# PORT1=$((1000 + OFFSET))
# PORT2=$((1001 + OFFSET))
# PORT3=$((1002 + OFFSET))
# PORT4=$((1003 + OFFSET))
# CRAPORT1=$((1004 + OFFSET))
# CRAPORT2=$((1005 + OFFSET))
if ! [ ${OFFSET:+defined} ]; then
OFFSET=0
fi
@ -37,22 +25,11 @@ PORT4=2001
CRAPORT1=1500
CRAPORT2=2500
ME=`whoami`
# ME=`whoami`
ME=rrnewton
CLIENTNAME=${ME}client${OFFSET}
SERVERNAME=${ME}server${OFFSET}
if ! which Ambrosia 2> /dev/null; then
echo "'Ambrosia' not found."
echo "You need Ambrosia on your PATH. Please download an AMBROSIA binary distribution."
exit 1
fi
if ! [ -e Client1/publish/Client1.dll ]; then
echo "Build products don't exist in ./Client1/publish."
echo "Did you run ./build_dotnetcore.sh yet?"
exit 1
fi
echo
echo "--------------------------------------------------------------------------------"
echo "HelloWorld with 2 instances all in this machine/container"
@ -60,24 +37,12 @@ echo " Instance: names $CLIENTNAME, $SERVERNAME"
echo "--------------------------------------------------------------------------------"
echo
if ! [ ${SKIP_REGISTER:+defined} ]; then
set -x
time Ambrosia RegisterInstance -i $CLIENTNAME --rp $PORT1 --sp $PORT2 -l "./ambrosia_logs/"
time Ambrosia RegisterInstance -i $SERVERNAME --rp $PORT3 --sp $PORT4 -l "./ambrosia_logs/"
set +x
fi
# Clear logs for this demonstration.
rm -rf ./ambrosia_logs/
echo "Running with AMBROSIA binaries from: "$(dirname `which runAmbrosiaService.sh`)
slog=`mktemp server.XXXX.log`
jlog=`mktemp client.XXXX.log`
echo
echo "PTI: Launching Server:"
set -x
AMBROSIA_INSTANCE_NAME=$SERVERNAME AMBROSIA_IMMORTALCOORDINATOR_PORT=$CRAPORT1 \
COORDTAG=CoordServ AMBROSIA_IMMORTALCOORDINATOR_LOG=$slog \
runAmbrosiaService.sh dotnet ./Server/publish/Server.dll $SERVERNAME
./run_helloworld_server.sh &
set +x
pid_server=$!
echo "Server launched as PID ${pid_server}. Waiting a bit."
@ -89,26 +54,22 @@ if ! kill -0 $pid_server 2>/dev/null ; then
echo
exit 1
fi
echo
echo "PTI: Launching Client1 now:"
set -x
AMBROSIA_INSTANCE_NAME=$CLIENTNAME AMBROSIA_IMMORTALCOORDINATOR_PORT=$CRAPORT2 \
COORDTAG=CoordCli AMBROSIA_IMMORTALCOORDINATOR_LOG=$jlog \
runAmbrosiaService.sh dotnet ./Client1/Publish/Client1.dll $CLIENTNAME $SERVERNAME
set +x
echo
echo "PTI Client finished, shutting down server."
echo "Launching Client1 now:"
./run_helloworld_client.sh
echo
echo "Client finished, shutting down server."
kill $pid_server
wait
echo "Everything shut down. All background processes done."
echo "Attempt a cleanup of our table metadata:"
echo "Finally, attempt a cleanup of our table metadata:"
set -x
UnsafeDeregisterInstance $CLIENTNAME || true
UnsafeDeregisterInstance $SERVERNAME || true
rm $slog $jlog
rm *-coord.*.log
set +x
echo "HelloWorld all done."

Просмотреть файл

@ -0,0 +1,42 @@
#!/bin/bash
[[ "$AZURE_STORAGE_CONN_STRING" =~ ';AccountName='[^\;]*';' ]] && \
echo "Using AZURE_STORAGE_CONN_STRING with account "${BASH_REMATCH}
set -euo pipefail
cd `dirname $0`
PORT1=1000
PORT2=1001
CRAPORT1=1500
ME=`whoami | sed 's/[^a-zA-Z0-9]//g'`
CLIENTNAME=${ME}client
SERVERNAME=${ME}server
if ! which Ambrosia 2> /dev/null; then
echo "'Ambrosia' not found."
echo "You need Ambrosia on your PATH. Please download an AMBROSIA binary distribution."
exit 1
fi
if ! [ -e Client1/publish/Client1.dll ]; then
echo "Build products don't exist in ./Client1/publish."
echo "Did you run ./build_dotnetcore.sh yet?"
exit 1
fi
echo
echo "HelloWorld Client Starting, name $CLIENTNAME"
echo
set -x
Ambrosia RegisterInstance -i $CLIENTNAME --rp $PORT1 --sp $PORT2 -l "./ambrosia_logs/"
set +x
clog=`mktemp client-coord.XXXX.log`
set -x
AMBROSIA_INSTANCE_NAME=$CLIENTNAME AMBROSIA_IMMORTALCOORDINATOR_PORT=$CRAPORT1 \
COORDTAG=CoordCli AMBROSIA_IMMORTALCOORDINATOR_LOG=$clog \
runAmbrosiaService.sh dotnet Client1/Publish/Client1.dll $CLIENTNAME $SERVERNAME
set +x
echo "HelloWorld Client finished."

Просмотреть файл

@ -0,0 +1,39 @@
#!/bin/bash
[[ "$AZURE_STORAGE_CONN_STRING" =~ ';AccountName='[^\;]*';' ]] && \
echo "Using AZURE_STORAGE_CONN_STRING with account "${BASH_REMATCH}
set -euo pipefail
cd `dirname $0`
PORT3=2000
PORT4=2001
CRAPORT2=2500
ME=`whoami | sed 's/[^a-zA-Z0-9]//g'`
SERVERNAME=${ME}server
if ! which Ambrosia 2> /dev/null; then
echo "'Ambrosia' not found."
echo "You need Ambrosia on your PATH. Please download an AMBROSIA binary distribution."
exit 1
fi
if ! [ -e Client1/publish/Client1.dll ]; then
echo "Build products don't exist in ./Client1/publish."
echo "Did you run ./build_dotnetcore.sh yet?"
exit 1
fi
echo
echo "HelloWorld Server Starting, name $SERVERNAME"
echo
set -x
Ambrosia RegisterInstance -i $SERVERNAME --rp $PORT3 --sp $PORT4 -l "./ambrosia_logs/"
set +x
slog=`mktemp server-coord.XXXX.log`
set -x
AMBROSIA_INSTANCE_NAME=$SERVERNAME AMBROSIA_IMMORTALCOORDINATOR_PORT=$CRAPORT2 \
COORDTAG=CoordServ AMBROSIA_IMMORTALCOORDINATOR_LOG=$slog \
runAmbrosiaService.sh dotnet Server/publish/Server.dll $SERVERNAME
set +x

Просмотреть файл

@ -133,7 +133,7 @@ function tail_tagged() {
# Side effect: runs a tail proycess in the background
function start_immortal_coordinator() {
echo " $TAG Launching coordinator with: ImmortalCoordinator" $*
if ! which ImmortalCoordinator; then
if ! which ImmortalCoordinator 2> /dev/null; then
echo " ERROR $TAG - ImmortalCoordinator not found on path!"
exit 1
fi
@ -150,28 +150,36 @@ function start_immortal_coordinator() {
fi
echo " $TAG Redirecting output to: $COORDLOG"
# OPTION (1): Bound logs, but complicated.
# ----------------------------------------
if which rotatelogs >/dev/null ; then
# Bound the total amount of output used by the ImmortalCoordinator log:
ImmortalCoordinator $* 2>&1 | rotatelogs -f -t "$COORDLOG" 10M &
coord_pid=$!
if [[ ${AMBROSIA_SILENT_COORDINATOR:+defined} ]]; then
# OPTION (1): No output from Coordinator to stdout/stderr:
ImmortalCoordinator $* 2>&1 > "$COORDLOG" &
coord_pid=$!
elif [ ${RUNAMBROSIA_USE_TAIL:+defined} ]; then
# OPTION (2): Bound logs, but complicated (and tends to leave stray tail processes)
# ---------------------------------------------------------------------------------
if which rotatelogs 2> /dev/null ; then
# Bound the total amount of output used by the ImmortalCoordinator log:
ImmortalCoordinator $* 2>&1 | rotatelogs -f -t "$COORDLOG" 10M &
coord_pid=$!
else
echo " ! WARNING $TAG: rotatelogs not available, NOT bounding size of $COORDLOG"
ImmortalCoordinator $* >>"$COORDLOG" 2>&1 &
coord_pid=$!
fi
if ! [[ ${AMBROSIA_SILENT_COORDINATOR:+defined} ]]; then
tail_tagged "$COORDTAG" "$COORDLOG"
fi
else
echo " ! WARNING $TAG: rotatelogs not available, NOT bounding size of $COORDLOG"
ImmortalCoordinator $* >>"$COORDLOG" 2>&1 &
coord_pid=$!
# OPTION (3) Just use tee. Don't bound coordinator log on disk.
# -------------------------------------------------------------
ImmortalCoordinator $* 2>&1 | tee "$COORDLOG" | tag_stdin "$COORDTAG" &
coord_pid=$!
fi
if ! [[ ${AMBROSIA_SILENT_COORDINATOR:+defined} ]]; then
tail_tagged "$COORDTAG" "$COORDLOG"
fi
# ----------------------------------------
# OPTION (2) Don't bound coordinator log on disk. Keep it simple:
# ImmortalCoordinator $* 2>&1 | tee "$COORDLOG" &
# coord_pid=$!
while ! grep -q "Ready" "$COORDLOG" && kill -0 $coord_pid 2>/dev/null ;
do sleep 2; done
if ! kill -0 $coord_pid 2>/dev/null ;
then echo
echo "--------------- ERROR $TAG ----------------"
@ -195,7 +203,7 @@ keep_monitoring=`mktemp healthMonitorContinue.XXXXXX`
touch $keep_monitoring
function monitor_health() {
echo " $TAG Health monitor starting coord_pid=$coord_pid, app_pid=$app_pid"
echo " $TAG Health monitor starting, coord_pid=$coord_pid, app_pid=$app_pid"
while [ -f $keep_monitoring ]; do
sleep 2
if ! kill -0 $coord_pid 2>/dev/null ; then
@ -220,18 +228,18 @@ start_immortal_coordinator -i $AMBROSIA_INSTANCE_NAME -p $AMBROSIA_IMMORTALCOORD
# Step 2:
echo " $TAG Launching app process alongside coordinator:"
set -x
# Test for interactive shell:
if tty -s; then
if [ -e /dev/stdin ]; then
set -x
$* < /dev/stdin &
set +x
app_pid=$!
else
set -x
$* &
set +x
app_pid=$!
fi
set +x
monitor_health &