Presentation is loading. Please wait.

Presentation is loading. Please wait.

ARCH-4: A Stateful Application in a Stateless World

Similar presentations


Presentation on theme: "ARCH-4: A Stateful Application in a Stateless World"— Presentation transcript:

1 ARCH-4: A Stateful Application in a Stateless World
Jamie Townsend Solutions Architect EMEA

2 Agenda The problem with Stateless today Different kinds of “State”
Maintaining State The Ideal Solution Getting There Conclusions ARCH-4: A stateful application in a stateless world

3 The good (very) old days: host-based
FIND FIRST Customer /* Process Customer 1 */ FIND NEXT Customer /* Process Customer 2 */ Everything on one box ARCH-4: A stateful application in a stateless world

4 The good (not so) old days: client/server
FIND FIRST Customer /* Process Customer 1 */ FIND NEXT Customer /* Process Customer 2 */ Client networking All code executes on the client Server ARCH-4: A stateful application in a stateless world

5 Improving network performance with the AppServer
CustProc.p RUN CustProc.p ON hAppServ (“FIRST”, OUTPUT ttCust) Business logic code executes on the server Client AppServer™ ARCH-4: A stateful application in a stateless world

6 Using a bound AppServer session in state-aware/state-reset mode
RUN CustProc.p ON hAppServer PERSISTENT set hCust. CustProc.p RUN FindCust IN hCust (“FIRST”, OUTPUT ttCust) /* Process Customer 1 */ RUN FindCust IN hCust (“NEXT”, OUTPUT ttCust) /* Process Customer 2 */ AppServer Client ARCH-4: A stateful application in a stateless world

7 Session Managed Model State-Aware and State-Reset Operating Modes
AppServer Client 1 AppServer Agents Agent 1 Client 2 Agent 2 ABL NameServer Data Client 3 Key point here is to understand how the connection is managed. This slide has many builds (each client is mouse build, all others are automatic, during the builds, Client 1 disconnects, allowing Client 4 to reuse that AppServer agent) to show that state-aware and state-reset are treated the same during the connection, that is the AppServer agent is dedicated to the client. On disconnect, the operating mode determines what happens to the context – state-aware it is maintained, where as in state-reset the server is “cleared out”. For both state-reset and state-aware - All requests sent by a client connected to this AppServer go to the same AppServer agent, which remains dedicated to the same client for the life of the connection. - One client per AppServer agent - Connection kept until disconnect - Dedicated connection - Throughput limited to number of server processes state-reset - When the client disconnects, the AppServer agent resets its context to what it was at startup, removing all context created during the terminated client connection. - Session state reset on disconnect state-aware - When the client disconnects, the AppServer agent deletes any remote persistent procedures that are still active in its context. However, it maintains all other context created during the terminated client connection for access during future client connections. This context remains available until it is removed during a future client connection or the AppServer agent terminates. - Session is maintained across connections - Can set context with startup procedure - Can use disconnect procedure to reset context Agent 3 Application Broker Client 4 Message Queue ARCH-4: A stateful application in a stateless world

8 Session Managed Model Stateless Operating Mode AppServer NameServer
Client 1 AppServer Agents Agent 1 Client 2 Application Broker Agent 2 ABL NameServer Data Client 3 Message Queue Stateless: A connection to a stateless AppServer is really a connection to the broker process. The client remains connected to the broker for the life of the connection. Each client request is sent to the next available AppServer agent which is not necessarily the same process as the one most recently accessed. Running the AppServer in Stateless mode allows a small number of agents to service many different client requests by not maintaining a one-to-one connection between the client and AppServer (unbound), however this means a client may get a different AppServer process on the next request, the AppServer will not know who you are or what you were doing in your last request. So you’ll need to “re-establish context” for that AppServer. Connection managed by AppServer broker Many clients per application server agent Context must be managed programmatically, unless changing to a bounded state. Establish/reset context with activate/deactivate procedures; complex to program if context required is complex. Maximum throughput under heavy client load where resources are limited and requests are short assuming minimal bound connections and connection context is small. Unlike state-reset or state-aware, an AppServer running in stateless operating mode does not dedicate any AppServer agent to a client connection. Instead, all AppServer agents remain generally available to execute remote procedure and user-defined function requests from all connected client applications. A connection in the unbound state can transition to the bound state in two ways: • A client application instantiates a remote persistent procedure in the context of the connection. The AppServer agent that handles the remote persistent procedure request thus becomes bound to the connection. • The AppServer agent runs a procedure that sets the SERVER-CONNECTION-BOUND-REQUEST attribute on the SESSION handle to TRUE. The AppServer agent that sets this attributes thus becomes bound in the connection. Agent 3 Client 4 ARCH-4: A stateful application in a stateless world

9 Using the AppServer in stateless mode– FIND FIRST
AppServer session 1 AppServer session RUN CustProc.p ON hAS (“FIRST”, OUTPUT ttCust) AppServer session AppServer broker AppServer session AppServer session AppServer session ARCH-4: A stateful application in a stateless world

10 Using the AppServer in stateless mode – FIND NEXT
AppServer session AppServer session 2 NEXT What?? RUN CustProc.p ON hAS (“NEXT”, OUTPUT ttCust) AppServer session AppServer broker AppServer session AppServer session AppServer session ARCH-4: A stateful application in a stateless world

11 Simply migrating your application to stateless AppServers
The Problem Simply migrating your application to stateless AppServers does not mean you have a stateless application ARCH-4: A stateful application in a stateless world

12 Agenda The problem with Stateless today Different kinds of “State”
Maintaining State The Ideal Solution Getting There Conclusions ARCH-4: A stateful application in a stateless world

13 Context vs. State vs. Operating Parameters
UI State (no impact on business logic) Business Logic Object State Operating Parameters State: - User Interface State is generally interesting for building interactive applications, but this should have absolutely no impact on the design of the business logic - Business Logic Object State is exactly what we want to avoid having in a stateless application. That is, within a request, they are probably necessary, but they should not span services requests. Examples might be variable values, temp-table buffers, query handles, etc. Business Logic Object State is highly volatile. Context: - Context data is more or less static throughout the life of an application session, regardless of the number of services requests made. Such data might include: username, login company, application language, Operating Parameters: - the input and output parameters required to make a given service request function correctly. ARCH-4: A stateful application in a stateless world

14 Context “Fixed” data for a session
Eg. User Name, Login Company, Language Must be restored with each Service Request Should be kept as small as practical Use CLIENT-PRINCIPAL State: - User Interface State is generally interesting for building interactive applications, but this should have absolutely no impact on the design of the business logic - Business Logic Object State is exactly what we want to avoid having in a stateless application. That is, within a request, they are probably necessary, but they should not span services requests. Examples might be variable values, temp-table buffers, query handles, etc. Business Logic Object State is highly volatile. Context: - Context data is more or less static throughout the life of an application session, regardless of the number of services requests made. Such data might include: username, login company, application language, Operating Parameters: - the input and output parameters required to make a given service request function correctly. ARCH-4: A stateful application in a stateless world

15 Context Using the CLIENT-PRINCIPAL CLIENT-PRINCIPAL Pass or Store
Instantiate (Authenticate) & Seal What to contain? Serialise/Deserialise How many? Pass or Store Context database must be secure and fast CLIENT-PRINCIPAL USER-ID SESSION-ID ROLES DOMAIN-NAME The client-principal object is the right ABL object to store context information. That said, it’s not a must to use the client-principal. The client-principal is expensive to instantiate and seal, so a better approach than doing this with every service request is to serialise and deserialse the object. Since only ABL client know what a client-principal object is, passing it backwards and forwards to/from the client/server will not always work. If it’s going to be store in a database on the server side, the database must be fast (-B <BIG>, -i, shared-memory, fast disc) and secure (username required for connection, secure directory, DBAUTHKEY) ARCH-4: A stateful application in a stateless world

16 Business Logic Object State
“Volatile” data for a session Eg. variable value, temp-tables, query position, etc. In Existing Application Possibly (probably) long lived May span multiple AppServer Requests In SOA Application Should not span Service Requests Not stored on server side State: - User Interface State is generally interesting for building interactive applications, but this should have absolutely no impact on the design of the business logic - Business Logic Object State is exactly what we want to avoid having in a stateless application. That is, within a request, they are probably necessary, but they should not span services requests. Examples might be variable values, temp-table buffers, query handles, etc. Business Logic Object State is highly volatile. Context: - Context data is more or less static throughout the life of an application session, regardless of the number of services requests made. Such data might include: username, login company, application language, Operating Parameters: - the input and output parameters required to make a given service request function correctly. ARCH-4: A stateful application in a stateless world

17 Operating Parameters “Fixed” data for single Service Request
Passed Client to Server and back Pass minimal dataset required Eg. Current Customer, Complete Order, etc. State: - User Interface State is generally interesting for building interactive applications, but this should have absolutely no impact on the design of the business logic - Business Logic Object State is exactly what we want to avoid having in a stateless application. That is, within a request, they are probably necessary, but they should not span services requests. Examples might be variable values, temp-table buffers, query handles, etc. Business Logic Object State is highly volatile. Context: - Context data is more or less static throughout the life of an application session, regardless of the number of services requests made. Such data might include: username, login company, application language, Operating Parameters: - the input and output parameters required to make a given service request function correctly. ARCH-4: A stateful application in a stateless world

18 Agenda The problem with Stateless today Different kinds of “State”
Maintaining “State” The Ideal Solution Getting There Conclusions ARCH-4: A stateful application in a stateless world

19 Sample Business Logic Validate Enter Customer Order Customer Entity
Entry Task Validate Customer if ? then Agreement Enter Order if ? then Customer Entity Order Entity Agreement Confirm Inventory if ? then Agreement Calculate Price if ? then The Entities can then be used to build up tasks that use multiple Entities and represent a controlled sequence of events with context maintained and decision points along the way. Inventory Entity Pricing Entity ARCH-4: A stateful application in a stateless world

20 Managing a task by …binding a stateless AppServer
Agreement Validate Customer if ? Context Enter Order Confirm Inventory Calculate Price Task RUN PERSISTENT DELETE PROCEDURE Client AppServer This method is strongly discouraged! - Uncontrolled binding to client - Not suitable for SOA direction ARCH-4: A stateful application in a stateless world

21 Managing a task by …passing state
RUN ... State Task if ? if ? Validate Customer State Agreement Enter Order RUN ... State State RUN ... State if ? Agreement Confirm Inventory Agreement Calculate Price State RUN ... State Context State Client AppServer Having state information available on the server side is necessary, but… This method is better + Stateless AS - SOA design - Client Maintains State - Performance ARCH-4: A stateful application in a stateless world

22 Managing a task by …saving state
RUN ... OP Validate Customer if ? OP Agreement RUN ... OP Enter Order State Store OP if ? Agreement RUN ... OP Confirm Inventory OP if ? Agreement RUN ... OP Calculate Price OP Client AppServer Pass less state – save it server side This is an alternative ? Performance - Service Request Dependency - Not SOA - Client must “know” state ARCH-4: A stateful application in a stateless world

23 Agenda The problem with Stateless today Different kinds of “State”
Maintaining State The Ideal Solution Getting There Conclusions ARCH-4: A stateful application in a stateless world

24 The Bigger Picture – Today and Tomorrow
Flexibility for client platforms and integration needs OpenEdge® AppServer OpenEdge .NET Interface .NET™ User Interface Jonas Grumby 110 Desert Isle Path Minnow, HI OK Cancel Purchase Order Business Logic Purchase Order Proxy PO ProDataSet™ Header Data C# Detail Data Other Data WebClient™ / HTML User Interface ABL or WebSpeed Interface OpenEdge ABL Interface Jonas Grumby OK 110 Desert Isle Path Cancel Minnow, HI OpenEdge Web Services Interface ABL ARCH-4: A stateful application in a stateless world

25 Encapsulation Required for SOA
Call Business Task OP Validate Customer OP OP OP Enter Order SOA Client OP OP Confirm Inventory OP OP Calculate Price AppServer SOA Clients need to access each of the steps separately. True SOA Application + Granular + Service Request Independency ? Performance ARCH-4: A stateful application in a stateless world

26 Encapsulation Required for SOA
Call Business Task Task RUN ... OP OP Validate Customer if ? OP Agreement OP RUN ... OP OP Enter Order if ? SOA Client Agreement RUN ... OP OP Confirm Inventory if ? Agreement RUN ... OP Calculate Price OP AppServer AppServer SOA Clients need to be able to access a business task containing multiple steps True SOA Application + Granular + Service Request Independency ? Performance ARCH-4: A stateful application in a stateless world

27 Agenda The problem with Stateless today Different kinds of “State”
Maintaining State The Ideal Solution Getting There Conclusions ARCH-4: A stateful application in a stateless world

28 What do I need to change? Pass required data as parameters
Refactor any “Block 0” objects DEFINE SHARED ... DEFINE VARIABLE DEFINE TEMP-TABLE DEFINE QUERY ...that change value ARCH-4: A stateful application in a stateless world

29 What do I need to change? AND DON’T FORGET…
Default Buffers for Database Tables!! PROCEDURE myProc: DEFINE BUFFER Customer FOR Customer. END PROCEDURE. ARCH-4: A stateful application in a stateless world

30 What do I need to change? DEFINE SHARED VARIABLE cUser AS CHARACTER NO-UNDO. DEFINE VARIABLE cWhere AS CHARACTER NO-UNDO. DEFINE QUERY qCust FOR customer. PROCEDURE initialiseQuery: cWhere = "salesrep = '" + cUser + "'". QUERY qCust:QUERY-PREPARE( "FOR EACH Customer WHERE " + cWhere). QUERY qCust:QUERY-OPEN(). END PROCEDURE. PROCEDURE getNextCustNum: DEFINE OUTPUT PARAMETER pCustNum AS INTEGER INIT ?. QUERY qCust:GET-NEXT(). IF AVAILABLE(Customer) THEN pCustNum = CustNum. This is a sample piece of State-Aware business logic that we want to refactor ARCH-4: A stateful application in a stateless world

31 What do I need to change? RUN initialiseQuery ON hAS. REPEAT:
RUN getNextCustNum ON hAS (OUTPUT iCustNum). IF iCustNum = ? THEN LEAVE. DISPLAY iCustNum. END. Here is how it is called from the client-side. ARCH-4: A stateful application in a stateless world

32 What do I need to change? DEFINE SHARED VARIABLE cUser AS CHARACTER NO-UNDO. DEFINE VARIABLE cWhere AS CHARACTER NO-UNDO. DEFINE QUERY qCust FOR customer. PROCEDURE initialiseQuery: cWhere = "salesrep = '" + cUser + "'". QUERY qCust:QUERY-PREPARE( "FOR EACH Customer WHERE " + cWhere). QUERY qCust:QUERY-OPEN(). END PROCEDURE. PROCEDURE getNextCustNum: DEFINE OUTPUT PARAMETER pCustNum AS INTEGER INIT ?. QUERY qCust:GET-NEXT(). IF AVAILABLE(Customer) THEN pCustNum = CustNum. getUser() Firstly, we want to remove any shared variables. In this case, we’re replacing the shared variable cUser with a call to a function getUser(). One might argue that cUser could be set when the AppServer agent initially receives the request (eg. As part of clearAndSetContextInformation) and while this is true, we want to avoid restoring any context (or is it state? :-) that is unnecessary. ARCH-4: A stateful application in a stateless world

33 What do I need to change? DEFINE QUERY qCust FOR customer.
PROCEDURE initialiseQuery: DEFINE VARIABLE cWhere AS CHARACTER NO-UNDO. cWhere = "salesrep = '" + getUser() + "'". QUERY qCust:QUERY-PREPARE( "FOR EACH Customer WHERE " + cWhere). QUERY qCust:QUERY-OPEN(). END PROCEDURE. PROCEDURE getNextCustNum: DEFINE OUTPUT PARAMETER pCustNum AS INTEGER INIT ?. QUERY qCust:GET-NEXT(). IF AVAILABLE(Customer) THEN pCustNum = CustNum. DEFINE VARIABLE cWhere AS CHARACTER NO-UNDO. DEFINE QUERY qCust FOR customer. PROCEDURE initialiseQuery: cWhere = "salesrep = '" + getUser() + "'". QUERY qCust:QUERY-PREPARE( "FOR EACH Customer WHERE " + cWhere). QUERY qCust:QUERY-OPEN(). END PROCEDURE. PROCEDURE getNextCustNum: DEFINE OUTPUT PARAMETER pCustNum AS INTEGER INIT ?. QUERY qCust:GET-NEXT(). IF AVAILABLE(Customer) THEN pCustNum = CustNum. Next we want to move the where clause from being a Block 0 variable into the procedure where it is used. Since cWhere is only used in one internal procedure here, it’s easy to do. If it were to be used in multiple internal procedures, it could be passed as parameters to each of the internal procedures. There might be a good reason to leave it at block 0, but in that case, it will have to be initialised at the start of each and every request. ARCH-4: A stateful application in a stateless world

34 What do I need to change? DEFINE QUERY qCust FOR customer.
PROCEDURE initialiseQuery: DEFINE VARIABLE cWhere AS CHARACTER NO-UNDO. cWhere = "salesrep = '" + getUser() + "'". QUERY qCust:QUERY-PREPARE( "FOR EACH Customer WHERE " + cWhere). QUERY qCust:QUERY-OPEN(). END PROCEDURE. PROCEDURE getNextCustNum: DEFINE OUTPUT PARAMETER pCustNum AS INTEGER INIT ?. QUERY qCust:GET-NEXT(). IF AVAILABLE(Customer) THEN pCustNum = CustNum. Now we get to the query, which is used in multiple internal procedures. As these internal procedures were previously called in separate AppServer requests, we’re now getting to the crux of our problem. We need to make sure that the query is initalised, even when the only AppServer call that we want to make is getNextCustNum ARCH-4: A stateful application in a stateless world

35 What do I need to change? Position Query
PROCEDURE initialiseQuery PRIVATE: DEFINE INPUT PARAMETER phQSales AS HANDLE NO-UNDO. DEFINE VARIABLE cWhere AS CHARACTER NO-UNDO. cWhere = "salesrep = '" + getUser() + "'". phQSales:QUERY-PREPARE( "FOR EACH Customer WHERE " + cWhere). phQSales:QUERY-OPEN(). END PROCEDURE. PROCEDURE getNextCustNum: DEFINE OUTPUT PARAMETER pCustNum AS INTEGER INIT ?. DEFINE QUERY qCust FOR customer. RUN initialiseQuery(QUERY qCust:HANDLE). QUERY qCust:GET-NEXT(). IF AVAILABLE(Customer) THEN pCustNum = CustNum. Position Query We want to mark the initialiseQuery procedure as PRIVATE because it should only be called internally. Next we need to make sure that the query is initialised by running initialiseQuery with each getNextCustNum request. Of course, we’ll also have to make sure that we correctly position the query, which we haven’t yet coded. To correctly do this, we need to make sure that every call to getNextCustNum passes in the current CustNum and that we step through the query until we find that CustNum. …but what happens if we’re sorting the query by another field? …and what if we used another where clause? ProDataSet’s restart rowid could be your friend ARCH-4: A stateful application in a stateless world

36 What do I need to change? RUN initialise ON hAS. REPEAT:
RUN getNextCustNum ON hAS (OUTPUT iCustNum). IF iCustNum = ? THEN LEAVE. DISPLAY iCustNum. END. Current CustNum So, getting back to our original code, we could now remove the call to initialise, add the parameter to show which customer record we currently have and then happily go and call getNextCustNum in a loop. Of course, this is not what we really want to do either. CLICK What we should really be doing is completely restructuring the client side code. Once we have done this, the service that we need to provide on the server side is a whole lot simpler. The main point here is that just restructuring your current code isn’t going to give you an SOA application. You need to design carefully. ARCH-4: A stateful application in a stateless world

37 What do I need to change? DEFINE TEMP-TABLE ttCust
FIELD CustNum AS INTEGER. RUN getListOfCustNums ON hAS (OUTPUT TABLE ttCustNums). FOR EACH ttCust: DISPLAY ttCust.CustNum. END. So, getting back to our original code, we could now remove the call to initialise, add the parameter to show which customer record we currently have and then happily go and call getNextCustNum in a loop. Of course, this is not what we really want to do either. CLICK What we should really be doing is completely restructuring the client side code. Once we have done this, the service that we need to provide on the server side is a whole lot simpler. The main point here is that just restructuring your current code isn’t going to give you an SOA application. You need to design carefully. ARCH-4: A stateful application in a stateless world

38 Encapsulation Required for SOA
RUN ... Call Business Task Task OP Validate Customer if ? Agreement OP RUN ... Enter Order if ? SOA Client Agreement RUN ... Confirm Inventory if ? Agreement RUN ... Calculate Price AppServer AppServer AppServer SOA Clients need to be able to access a business task containing multiple steps True SOA Application + Granular + Service Request Independency + Performance ARCH-4: A stateful application in a stateless world

39 Agenda The problem with Stateless today Different kinds of “State”
Maintaining State The Ideal Solution Getting There Conclusions ARCH-4: A stateful application in a stateless world

40 Conclusions Stateless AppServer <> Stateless Application
requires Stateless Design Test with stateless AppServers ARCH-4: A stateful application in a stateless world

41 In Other Words Stateless AppServer <> Stateless Application
requires Stateless Design Test with stateless AppServers Stateless is not hard… …making it perform is Refactoring is not redesign!! Develop with stateless AppServers ARCH-4: A stateful application in a stateless world

42 Relevant Exchange Sessions
ARCH-1: Application Architecture Made Simple ARCH-13: Transactions in an SOA World INT-3: Realistic Service Oriented Architecture Approaches INT-10: Understanding The AppServer, Inside-out ARCH-4: A stateful application in a stateless world

43 Questions? ARCH-4: A stateful application in a stateless world

44 Thank you for your time ARCH-4: A stateful application in a stateless world

45 ARCH-4: A stateful application in a stateless world


Download ppt "ARCH-4: A Stateful Application in a Stateless World"

Similar presentations


Ads by Google