LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
gallery_multitier.m
1% Layered Queueing Network (LQN) - Production 4-Tier J2EE Architecture Model
2%
3% This example demonstrates a comprehensive 4-layer J2EE system architecture:
4%
5% Layer 1: CLIENT LAYER
6% - Reference task with 1 user (closed class)
7% - Represents browser clients with sequential user operations
8%
9% Layer 2: APPLICATION LAYER
10% - Service task handling 4 concurrent web requests
11% - Multiple entries (renderHomePage, processProductPage, handleLogin, checkoutWorkflow)
12% - Complex activity precedence with or-fork/or-join branching
13%
14% Layer 3: DATABASE LAYER
15% - Service task managing database operations
16% - Multiple entries for different query types (read, write, query, log)
17% - Sequential activity chains
18%
19% The model demonstrates:
20% - Multiple entries per task
21% - Complex activity precedence patterns (serial, or-fork, or-join)
22% - Synchronous call routing between layers
23% - Load-dependent processing characteristics
24% - Production-grade LQN features
25%
26% This is a reference model for validating SolverLN against complex layered systems.
27% For cache support variant, see: example_layered_production_4tier_cache.m
28
29clear all;
30
31%% Create the model
32model = LayeredNetwork('testLQN3');
33
34%% Layer 1: CLIENT LAYER
35P0 = Processor(model, 'P0', 1, SchedStrategy.PS);
36T0 = Task(model, 'T0', 1, SchedStrategy.REF).on(P0); % Reference task with 1 user
37E0 = Entry(model, 'E0').on(T0); % Single entry point for all client requests
38
39%% Layer 2: APPLICATION SERVER LAYER
40P1 = Processor(model, 'P1', 1, SchedStrategy.PS);
41T1 = Task(model, 'T1', 1, SchedStrategy.FCFS).on(P1); % FCFS for serialization
42E10 = Entry(model, 'E10').on(T1); % renderHomePage
43E11 = Entry(model, 'E11').on(T1); % processProductPage
44E12 = Entry(model, 'E12').on(T1); % handleLogin
45E13 = Entry(model, 'E13').on(T1); % checkoutWorkflow
46
47%% Layer 3: DATABASE LAYER
48P2 = Processor(model, 'P2', 1, SchedStrategy.PS);
49T2 = Task(model, 'T2', 1, SchedStrategy.FCFS).on(P2); % Database serialization
50E20 = Entry(model, 'E20').on(T2); % readUserProfile
51E21 = Entry(model, 'E21').on(T2); % getProductInfo
52E22 = Entry(model, 'E22').on(T2); % writeOrderData
53E23 = Entry(model, 'E23').on(T2); % logSessionEvent
54
55%% CLIENT LAYER ACTIVITIES
56% Sequential processing flow: login → browse → shop → checkout
57A0 = Activity(model, 'A0', Exp(1.0)).on(T0).boundTo(E0).synchCall(E12, 1.0); % login -> handleLogin
58A1 = Activity(model, 'A1', Exp(1.0)).on(T0).synchCall(E10, 1.0); % browseSession -> renderHomePage
59A2 = Activity(model, 'A2', Exp(1.0)).on(T0).synchCall(E11, 1.0); % viewProductPage -> processProductPage
60A3 = Activity(model, 'A3', Exp(1.0)).on(T0).synchCall(E13, 1.0); % submitCheckout -> checkoutWorkflow
61
62%% APPLICATION LAYER ACTIVITIES
63% Entry E10: renderHomePage
64B0 = Activity(model, 'B0', Exp(1.0)).on(T1).boundTo(E10); % renderStaticContent
65B1 = Activity(model, 'B1', Exp(1.0)).on(T1).repliesTo(E10); % fetchRecommendations
66
67% Entry E11: processProductPage
68B2 = Activity(model, 'B2', Exp(1.0)).on(T1).boundTo(E11); % parseRequest
69B3 = Activity(model, 'B3', Exp(1.0)).on(T1).synchCall(E21, 1.0).repliesTo(E11); % getProductDetails -> getProductInfo
70
71% Entry E12: handleLogin
72B4 = Activity(model, 'B4', Exp(1.0)).on(T1).boundTo(E12).synchCall(E20, 1.0).repliesTo(E12); % validateCredentials -> readUserProfile
73
74% Entry E13: checkoutWorkflow
75B5 = Activity(model, 'B5', Exp(1.0)).on(T1).boundTo(E13); % verifyCart
76B6 = Activity(model, 'B6', Exp(1.0)).on(T1); % computeTotalPrice
77B7 = Activity(model, 'B7', Exp(1.0)).on(T1).synchCall(E22, 1.0); % WriteOrder
78B7a = Activity(model, 'B7a', Exp(1.0)).on(T1); % skipLog (30% probability)
79B7b = Activity(model, 'B7b', Exp(1.0)).on(T1).synchCall(E23, 1.0); % logOrder (70% probability)
80B8 = Activity(model, 'B8', Exp(1.0)).on(T1).repliesTo(E13); % success
81
82%% DATABASE LAYER ACTIVITIES
83% Entry E20: readUserProfile
84C0 = Activity(model, 'C0', Exp(1.0)).on(T2).boundTo(E20); % parseReadQuery
85C1 = Activity(model, 'C1', Exp(1.0)).on(T2).repliesTo(E20); % fetchFromDisk
86
87% Entry E21: getProductInfo
88C2 = Activity(model, 'C2', Exp(1.0)).on(T2).boundTo(E21).repliesTo(E21); % readCache (in-DB cache)
89
90% Entry E22: writeOrderData
91C3 = Activity(model, 'C3', Exp(1.0)).on(T2).boundTo(E22); % parseWriteQuery
92C4 = Activity(model, 'C4', Exp(1.0)).on(T2); % writeToDisk
93C5 = Activity(model, 'C5', Exp(1.0)).on(T2).repliesTo(E22); % updateIndex
94
95% Entry E23: logSessionEvent
96C6 = Activity(model, 'C6', Exp(1.0)).on(T2).boundTo(E23).repliesTo(E23); % appendToLog
97
98%% ACTIVITY PRECEDENCES - CLIENT LAYER
99% Sequential flow through all client operations
100T0.addPrecedence(ActivityPrecedence.Serial(A0, A1, A2, A3));
101
102%% ACTIVITY PRECEDENCES - APPLICATION LAYER
103% Path 1: renderHomePage flow
104T1.addPrecedence(ActivityPrecedence.Serial(B0, B1));
105
106% Path 2: processProductPage flow
107T1.addPrecedence(ActivityPrecedence.Serial(B2, B3));
108
109% Path 3: checkoutWorkflow flow with branching
110T1.addPrecedence(ActivityPrecedence.Serial(B5, B6, B7)); % Sequential: verify -> compute -> write
111T1.addPrecedence(ActivityPrecedence.OrFork(B7, {B7a, B7b}, [0.7, 0.3])); % 70% skip, 30% log
112T1.addPrecedence(ActivityPrecedence.OrJoin({B7a, B7b}, B8)); % Converge branches to success
113
114%% ACTIVITY PRECEDENCES - DATABASE LAYER
115% Query path 1: readUserProfile
116T2.addPrecedence(ActivityPrecedence.Serial(C0, C1));
117
118% Query path 2: writeOrderData with index update
119T2.addPrecedence(ActivityPrecedence.Serial(C3, C4, C5));
120
121%% SOLVE WITH SOLVERMVA (Layer solver) inside SolverLN
122fprintf('\n=== Solving 4-Tier LQN with SolverLN + MVA ===\n');
123lnoptions = LN.defaultOptions;
124lnoptions.verbose = VerboseLevel.STD;
125mvaopt = MVA.defaultOptions;
126mvaopt.verbose = VerboseLevel.SILENT;
127
128solver = LN(model, @(layer) MVA(layer, mvaopt), lnoptions);
129AvgTable = solver.getAvgTable;
130
131fprintf('\n=== Results ===\n');
132disp(AvgTable);
133
134%% Alternative: Solve with SolverFluid (approximation)
135% Uncomment to compare with fluid approximation
136% fprintf('\n=== Solving 4-Tier LQN with SolverLN + SolverFluid (Approximation) ===\n');
137% lnoptions = LN.defaultOptions;
138% lnoptions.verbose = VerboseLevel.STD;
139% fluidopt = SolverFluid.defaultOptions;
140% fluidopt.verbose = VerboseLevel.SILENT;
141%
142% solver_fluid = LN(model, @(layer) SolverFluid(layer, fluidopt), lnoptions);
143% AvgTable_fluid = solver_fluid.getAvgTable;
144% disp('Fluid Approximation Results:');
145% disp(AvgTable_fluid);