辅导案例-COMPSCI 711 1-Assignment 2

欢迎使用51辅导,51作业君孵化低价透明的学长辅导平台,服务保持优质,平均费用压低50%以上! 51fudao.top
COMPSCI 711 1 radu/2020
Assignment 2
Assignment 1 required the design and develop a faithful sequential emulation of the
Echo algorithm, extended to determine the size of the network.
Assignment 2 requires two non-sequential versions of Assignment 1’s solution:
1. A multi-threaded implementation using channels, as available in
System.Threading.Channels.
2. A multi-process implementation based on HTTP services, as available via ASP.NET Core
- additional layers such as WebAPI (REST), Carter, gRPC are acceptable (but please ask).
As before, there is a central message dispatcher called Arcs, which can also act as virtual
node 0. Arcs read the input config from stdin and traces messages on standout, using the
same conventions, constraints, specs. You can your own sequential solution for A#1, or
the model solution, or a combination of both (your choice).
To minimize the changes, use the following blueprint, where thin lines represent
procedure calls, thick line channels or HTTP request/responses, and dotted lines an
optional initialisation component:

A good implementation will localise most of the communication specifics in the proxy
classes, and then the main Arcs and Node classes will be virtually the same.
In the Channels version, all components are included in the same source file.
In the HTTP version, the arcs process is described in one file, and the node process in
another. Each node will start its own HTTP service, listening at port 8080+node number.

COMPSCI 711 2 radu/2020
Development language and platform
C#, for .NET Core 3.1.X (which is free, open source, cross-platform, and LTS).

Marks: 7 course marks
Part I: 3 marks
Part II: 4 marks, plus 1 bonus mark for each of the other two alternatives

Submission
For part 1 (Channels), submit to automarker:
https://www.automarker.cs.auckland.ac.nz/student.php
Submit just one single C# source file, named as UPI.cs.
For part 2 (HTTP), submit to ADB:
https://adb.auckland.ac.nz/
Submit two C# source files, named as UPI-arcs.cs and UPI-node.cs.
For both parts, replace UPI by your actual university ID, e.g. jbon007.
Ensure that all programs terminate properly, otherwise you may get timeout errors.

Readings
An Introduction to System.Threading.Channels
https://devblogs.microsoft.com/dotnet/an-introduction-to-system-threading-channels/
System.Threading.Channels Namespace
https://docs.microsoft.com/en-
us/dotnet/api/system.threading.channels?view=netcore-3.1
Create web APIs with ASP.NET Core
https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-3.1
Carter
https://github.com/CarterCommunity/Carter
gRPC
https://docs.microsoft.com/en-us/aspnet/core/grpc/?view=aspnetcore-3.1

COMPSCI 711 3 radu/2020
gRPC Appendix

A#2.2 FAQ - Problems and solutions

Problems
o Multiple servers starting on the same code base -- concurrent updates
o Process API ok for console and UI apps, but less for server apps
o Process API redirection complicated
o Servers have unpredictable startup delays -- ensure they are listening
o Servers may accidentally hang -- self stop, outside (Arcs) stop

Solutions
o Projects structure: Arcs contains a Node subfolder, for the node services
o Arcs write out starting batch script -- .bat, .sh
o Servers start with delays -- 1 sec?
o Arcs calls this batch via Process.Start -- does not directly start individual node
servers
o Before starting, Arcs pings each url with a new AYT (AreYouThere) message
o After ending its message dispatching loop (normally or on exceptions), Arcs send
out STOP messages
o Each node stops itself after sending out the Return message

Demo
o At the lecture / tutorial


COMPSCI 711 4 radu/2020
Protobuf file node.proto – MANDATORY!

syntax = "proto3";

option csharp_namespace = "Echo";

package echosize;

// The service definition.
service Node {
rpc Process (MsgArray) returns (MsgArray);
}

// The request/response message.
message MsgArray {
message Msg {
int32 time = 1;
int32 code = 2;
int32 from = 3;
int32 to = 4;
int32 tok = 5;
int32 pay = 6;
}
repeated Msg Msgs = 1;
}

COMPSCI 711 5 radu/2020
Project layout
Arcs folder
Bin folder
Node folder – for Node project
Bin folder
Obj folder
Protos folder – with mandatory node.proto
files
Obj folder
Protos folder – with mandatory node.proto
files

Sample startup .bat script generated by Arcs, on Windows
Assuming test case #1, with four nodes, 1, 2, 3, 4:
start "node_1" cmd /k
.\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.exe 1 2 3 4
timeout 1
start "node_2" cmd /k
.\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.exe 2 1 3
timeout 1
start "node_4" cmd /k
.\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.exe 4 3 1
timeout 1
start "node_3" cmd /k
.\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.exe 3 1 2 4
timeout 1
Sorry for the four wrapped lines.

COMPSCI 711 6 radu/2020
Testing .bat script for Windows

@set PROMPT=$G

dotnet build a2-model-arcs-grpc.csproj
@pause

@set EchoNodePath=dotnet run -p .\Node\a2-model-node-grpc.csproj --
@set EchoNodePath=
.\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.exe
@set EchoNodePath=
dotnet .\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.dll
@echo EchoNodePath=%EchoNodePath%

@for /l %%X in (1, 1, 10) do @(
rem dotnet run -p a2-model-arcs-grpc.csproj -- %EchoNodePath%
< a2-inp%%X.txt > a2-outp%%X-test.txt
rem .\bin\Debug\netcoreapp3.1\a2-model-arcs-grpc.exe %EchoNodePath%
< a2-inp%%X.txt > a2-outp%%X-test.txt
dotnet .\bin\Debug\netcoreapp3.1\a2-model-arcs-grpc.dll %EchoNodePath%
< a2-inp%%X.txt > a2-outp%%X-test.txt
rem type a2-outp%%X.txt
fc a2-outp%%X.txt a2-outp%%X-test.txt
pause
)
pause
Sorry for the four wrapped lines.
To minimise delays and reduce the conflicts likelihood, prefer the path that points to
the exe or dotnet dll (not dotnet run-ning the project, which implies a build).
Please note that Arcs takes one command line argument = the path to run the Node
project (no spaces assumed).

COMPSCI 711 7 radu/2020
Testing .sh script for *nix and *nix enabled Windows – tested on Windows only!
#!/bin/bash
set +v
function pause () {
read -n1 -p "Press any key to continue . . ."
echo
}
set -v
dotnet build a2-model-arcs-grpc.csproj
set +v
pause
EchoNodePath="dotnet run -p .\Node\a2-model-node-grpc.csproj --"
EchoNodePath=
"dotnet .\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.dll"
echo EchoNodePath=$EchoNodePath
#for ((X=1; X<=10; X++))
for X in {1..10}
do
#dotnet run -p a2-model-arcs-grpc.csproj -- $EchoNodePath
< a2-inp$X.txt > a2-outp$X-test.txt
dotnet ./bin/Debug/netcoreapp3.1/a2-model-arcs-grpc.dll $EchoNodePath
< a2-inp$X.txt > a2-outp$X-test.txt
#cat a2-outp$X.txt
diff --strip-trailing-cr a2-outp$X.txt a2-outp$X-test.txt
echo a2 case $X : $?
pause
done
pause
Sorry for the three wrapped lines.

COMPSCI 711 8 radu/2020
Singletons in ASP.NET
public void ConfigureServices (IServiceCollection services) {

services.AddSingleton (); // !!!
}

New message tokens:
public readonly static int TokAYT = 0; // ayt
public readonly static int TokSTOP = 3; // stop

Arcs stops all nodes by broadcasting STOP messages
In proxy:
public async Task STOP () {
try {
Console.Error.WriteLine ($"... STOP NODE={Self}");
await Process (new[] {new Message (0, 1, 0, Self, Message.TokSTOP, 0)});
} catch (Exception ex) {
_ = ex;
Console.Error.WriteLine ($"*** STOP NODE={Self} UNREACHABLE");
}
}

After the dispatching loop (assuming that nn.Value is a proxy):
foreach (var nn in nodes) {
await nn.Value.STOP ();
}


COMPSCI 711 9 radu/2020
Node stops itself, if completed or required
Call Stop when you want to stop, e.g. just before sending the return, or after receiving a
stop message -- but w/o awaiting its completion!
public async Task Stop () {
await Task.Delay (100);
_logger.Log (LogLevel.Information, $"... STOP");
Environment.Exit (0);
}

Arcs tests that a node service has really started
In proxy, call AYT 3 times, at 1 sec intervals:
public async Task AYT () {
var count = 0;
while (true) {
try {
count += 1;
Console.Error.WriteLine ($"... AYT NODE={Self} ({count})");
await Process (new[] {new Message (0, 1, 0, Self, Message.TokAYT, 0)});
break;
} catch (Exception ex) {
_ = ex;
Console.Error.WriteLine ($"*** AYT NODE={Self} ({count})");
await Task.Delay (1000);
}
if (count == 3) {
throw new Exception ($"AYT {Self}");
}
}
}

51作业君

Email:51zuoyejun

@gmail.com

添加客服微信: abby12468