UNPKG

26.5 kBMarkdownView Raw
1# Contents
2
3- [Notes on MicroService Networking](#notes-on-microservice-networking)
4- [Networking Options](#networking-options)
5- [Co-hosted QEWD MicroServices](#co-hosted-qewd-microServices)
6 - [Setting up Docker Networking](#setting-up-docker-networking)
7 - [Setting up the Orchestrator](#setting-up-the-orchestrator)
8 - [Setting up a MicroService Instance](#setting-up-a-microservice-instance)
9- [Separately-hosted QEWD MicroServices](#separately-hosted-qewd-microServices)
10 - [Setting up a Separately-Hosted Orchestrator](#setting-up-a-separately-hosted-orchestrator)
11 - [Setting up a Separately-Hosted MicroService](#setting-up-a-separately-hosted-microservice)
12- [Confirming that the MicroServices are Communicating](#confirming-that-the-microservices-are-communicating)
13 - [Stopping and Starting the QEWD-Up Instances](#stopping-and-starting-the-qewd-up-instances)
14- [Persisting Data in the Integrated YottaDB Database](#persisting-data-in-the-integrated-yottadb-database)
15 - [Installing the Pre-Initialised YottaDB Database Files](#installing-the-pre-initialised-yottadb-database-files)
16 - [Mapping the YottaDB Files at Startup](#mapping-the-yottadb-files-at-startup)
17- [Monitoring the QEWD Activity of your QEWD Docker Instances](#monitoring-the-qewd-activity-of-your-qewd-docker-instances)
18- [Using the qewd-monitor Application](#using-the-qewd-monitor-application)
19
20
21# Notes on MicroService Networking
22
23QEWD-Up's MicroService mode makes use of multiple Docker containers, each one being an instance of QEWD.
24
25All incoming REST requests are received by the QEWD instance that is designated to be the *Orchestrator*. Its role is to forward most, if not all, of the incoming requests to the other QEWD instances that act as MicroServices.
26
27In order for this to be possible, you need to understand:
28
29- how to tell the *Orchestrator* where to find the MicroService instances, so that it can make and maintain its WebSocket connections to them
30
31- how to make the *Orchestrator* accessible to your external REST clients
32
33- optionally, how to make the MicroServices externally accessible to allow monitoring via the *qewd-monitor* application.
34
35These notes aim to address these issues
36
37# Networking Options
38
39It is up to you where each QEWD Docker instance is physically hosted: they can all run on the same host machine or they can be distributed across multiple host machines.
40
41The simplest scenario is where the *Orchestrator* and all the MicroService instances are co-hosted on the same physical Docker host, and it is recommended that this scenario is used for your initial experiments with QEWD-Up until you become familiar with its operation.
42
43In advanced production environments, you'll also probably want to front-end your QEWD-Up architecture with a reverse proxy and/or load-balancer. *NGINX* is an ideal solution for this. If scaling becomes an issue, *NGINX* can also be used to front-end multiple instances of each MicroService.
44
45# Co-hosted QEWD MicroServices
46
47## Setting up Docker Networking
48
49The simplest, most secure and least problematic way to get a Co-hosted set of QEWD-Up MicroServices to inter-operate is to make use of Docker's networking. To do this, assuming you already have Docker installed, configured and working, you should run the following command to create our own new bridged Docker network that will be used exclusively by your QEWD-Up *Orchestrator* and MicroServices. You should only need to invoke this command once:
50
51 docker network create qewd-net
52
53Note: you can name the network anything you like, but the examples that follow in this document assume you've used the name *qewd-net* as above.
54
55You can check that the command has worked and that the *qewd-net* network is present by using:
56
57 docker network ls
58
59You should see something like this, showing the *qewd-net* network exists and is a bridged network:
60
61 NETWORK ID NAME DRIVER SCOPE
62 759c78b28079 bridge bridge local
63 48a2b67122aa host host local
64 36856a4ed61b none null local
65 525eb2f9b7bc qewd-net bridge local
66
67
68## Setting up the Orchestrator
69
70The key aspects in setting up the *Orchestrator* QEWD-Up service are handled by the *docker run* command that you use to start it up. These are:
71
72- its Docker name, by which it can be referred for system management and monitoring purposes
73- whether you want the Docker instance to run:
74 - as a foreground process in a terminal window, which is useful when getting started with QEWD-Up and when debugging
75 - as a background *daemon* process (which can still be logged using the *docker logs* command)
76- the Docker network that it should use
77- the host TCP port on which it is accessed
78- the volume mapping, by which the QEWD-Up configuration, routing and handler definitions are made accessible to the *Orchestrator's* Docker environment
79- optionally, the volume mapping that allows YottaDB (the integrated JSON storage database) to persist its data even if the *Orchestrator* Docker instance is stopped and restarted.
80
81The command to start/restart the Orchestrator is as follows:
82
83 docker run
84 -it | -d (foreground v daemon)
85 --name {Docker instance name}
86 --rm (recommended, to remove the instance from cache when shut down)
87 --net {Docker network name}
88 -p {external port}:8080 (by default, QEWD-Up configures to listen on port 8080)
89 -v {QEWD-Up Configuration Directory}:/opt/qewd/mapped
90 -v {YottaDB persistent file directory}:/root/.yottadb/r1.22_x86_64/g (optional)
91
92 rtweed/qewd-server | rtweed/qewd-server-rpi (Linux v Raspberry Pi QEWD Docker library)
93
94For example:
95
96 docker run -it --name orchestrator --rm --net qewd-net -p 3000:8080 -v ~/ms-db:/opt/qewd/mapped rtweed/qewd-server
97
98This will start the *Orchestrator* service:
99
100- as a foreground process
101- with a Docker process name of *orchestrator* by which it can be referred and monitored via other Docker commands
102- such that, when stopped, it is removed from Docker's cache
103- using the network that we created and named *qewd-net* (see previous section)
104- with QEWD's Web Server (and therefore its REST interface) accessible via port 3000 on the Docker host machine
105- using the QEWD-Up configuration file folder at *~/ms-db* on the Docker host machine
106- using the Linux version of the Dockerised QEWD library
107
108Note that, depending on how you've configured Docker on the host machine, you may need to prefix the *docker run* command with *sudo*, eg:
109
110 sudo docker run -it --name orchestrator --rm -p 3000:8080 -v ~/ms-db:/opt/qewd/mapped rtweed/qewd-server
111
112
113If the host machine on which you invoked this *docker run* command had an IP address of *204.50.20.2*, then your REST Client would send its requests to:
114
115 {api method} http://204.50.20.2:3000/{api path}
116
117eg:
118
119 GET http://204.50.20.2:3000/api/info
120
121
122## Setting up a MicroService Instance
123
124There are three parts to setting up a QEWD-Up MicroService instance:
125
126- the information needed by the *Orchestrator* to discover and connect to the MicroService
127- optionally, how to access the MicroService externally, if you want to be able, for example, to monitor it using the integrated *qewd-monitor* browser-based application
128- the *docker run* options needed to start it up
129
130By using our own Docker network (*qewd-net* in our case), we can just use the Docker name that we specify when starting up the MicroService, and let Docker's *automatic discovery service* pull everything else together for us.
131
132For example, if we have a MicroService that is responsible for user login/authentication, we might decide to name it *login_service*. All we need to do is ensure that we use this name consistently within the *config.json* file and the *docker run* command when starting it up.
133
134So, in the */configuration/config.json* file, we would specify it as follows:
135
136 {
137 "qewd_up": true,
138 "orchestrator": {
139 "qewd": {
140 "serverName": "Orchestrator"
141 }
142 },
143 "microservices": [
144 {
145 "name": "login_service",
146 "qewd": {
147 "serverName": "Login MicroService"
148 }
149 }
150 ]
151 }
152
153This provides all the information the *Orchestrator* will need to discover and connect to the *login_service* MicroService, **provided** we use our *qewd-net* Docker bridged network.
154
155The *docker run* command used to start/restart a QEWD-Up MicroService is very similar to that used to start the Orchestrator, but **MUST** include the additional *-e* parameter:
156
157 docker run
158 -it | -d (foreground v daemon)
159 --name {MicroService name}
160 --rm (recommended, to remove the instance from cache when shut down)
161 --net {Docker network name}
162 -p {external port}:8080 (optional. By default, QEWD-Up configures to listen on port 8080)
163 -e microservice="{MicroService Name}"
164 -v {QEWD-Up Configuration Directory}:/opt/qewd/mapped
165 -v {YottaDB persistent file directory}:/root/.yottadb/r1.22_x86_64/g (optional)
166
167 rtweed/qewd-server | rtweed/qewd-server-rpi (Linux v Raspberry Pi QEWD Docker library)
168
169So, to start up our *login_service* MicroService, we could invoke the command:
170
171 docker run -it --name login_service --rm --net qewd-net -v ~/ms-db:/opt/qewd/mapped -e microservice="login_service" rtweed/qewd-server
172
173
174**IMPORTANT**: You **MUST** specify both the *--name** and *-e* parameters, and they both **MUST** have the same value which **MUST** match the MicroService name in the *config.json* file.
175
176If you want to be able to monitor the *login_service* MicroService QEWD instance using its *qewd-monitor* application, you must make it accessible via a host TCP port. You do this by adding the *-p* parameter, eg:
177
178 docker run -it --name login_service --rm --net qewd-net -p 3001:8080 -v ~/ms-db:/opt/qewd/mapped -e microservice="login_service" rtweed/qewd-server
179
180This would make it accessible via the host's port 3001.
181
182# Separately-hosted QEWD MicroServices
183
184In order to distribute the load imposed by your individual MicroServices, you may decide to host them on separate physical servers (or Virtual Machines).
185
186In this scenario, we can't use within-host Docker networking, and must use alternative mechanisms. One basic mechanism is to use the hosts' own networking and ensure that each MicroService Web Server listener port is mapped to a TCP port on its host machine. We can then use the explicit *host* and *port* properties within your *config.json* file.
187
188## Setting up a Separately-Hosted Orchestrator
189
190Let's suppose we want to run the *Orchestrator* on a host whose IP address is *204.50.20.2* and our QEWD-Up application is defined within the folder *~/ms-db*.
191
192We might start it up using:
193
194 docker run -it --name orchestrator --rm -p 3000:8080 -v ~/ms-db:/opt/qewd/mapped rtweed/qewd-server
195
196Note that in this scenario, we don't need to use a separately-defined Docker network, because this is the only Docker instance that we'll run on this host.
197
198Now let's suppose that we'll be running a MicroService named *login_service* on another physical host machine whose IP address is *204.50.20.3*, to which the *Orchestrator* needs to connect.
199
200We could set this up in the *config.json* file (ie *~/ms-db/configuration/config.json*) on the *Orchestrator* host as follows:
201
202 {
203 "qewd_up": true,
204 "orchestrator": {
205 "qewd": {
206 "serverName": "Orchestrator"
207 }
208 },
209 "microservices": [
210 {
211 "name": "login_service",
212 "host": "204.50.20.3",
213 "port": 3000,
214 "qewd": {
215 "serverName": "Login MicroService"
216 }
217 }
218 ],
219 "jwt": {
220 "secret": "mySharedJWTSecretString"
221 }
222 }
223
224**Note**: We've added a *jwt.secret* property to the file. This is used to sign and authenticate the JWTs that are used by QEWD's MicroServices.
225
226In a co-hosted scenario this explicit definition of the JWT Secret is unnecessary, because a random Uid-formatted value is automatically added by the first QEWD-Up instance you start, and is then shared by all the other QEWD-Up instances when you start them.
227
228However, if the MicroServices are running on separate physical hosts, then the JWT Secret sharing must be done by you.
229
230The value of the JWT Secret can be any string value, but it is recommended that you use a value that cannot be easily guessed. A randomly-generated Uid-formatted value is recommended.
231
232In the example *config.json* file above, the *Orchestrator* will therefore expect to find and connect to the *login_service* MicroService via a host IP address of *204.50.20.3* and TCP port of 3000.
233
234
235## Setting up a Separately-Hosted MicroService
236
237Continuing with the example above, we want to now set up a MicroService named *login_service* on a host machine whose IP address is *204.50.20.3* and which the Orchestrator can connect to via the host's TCP port 3000.
238
239The first step is to copy the folder and its contents from *~/ms-db* on the *Orchestrator* to a folder on our MicroService host machine. For convenience, we'll use the same directory name: *~/ms-db*.
240
241As shown in the previous section, the *config.json* file must already include a *jwt.secret* property. **Leave this in place and unchanged!**
242
243Now start up the *login_service* MicroService using:
244
245 docker run -it --name login_service --rm -p 3000:8080 -v ~/ms-db:/opt/qewd/mapped -e microservice="login_service" rtweed/qewd-server
246
247You should see the [connection activity and registration handshaking](#confirming-that-the-microservices-are-communicating) taking place in the terminal windows where you're running the *Orchestrator* and *login_service* Docker instances.
248
249Your QEWD-Up services are now ready for use. You should now be able to send REST requests to the *Orchestrator* at:
250
251 {method} http://204.50.20.2:3000/{api-path}
252
253eg:
254
255 POST http://204.50.20.2:3000/api/login
256
257This request should generate the appropriate activity on the *login_service* MicroService on its host machine at *204.50.20.3* as a result of invoking the */api/login* API handler method.
258
259
260# Confirming that the MicroServices are Communicating
261
262Something that you'll want to be able to confirm is whether or not the *Orchestrator* has been able to successfully find and connect to its MicroServices.
263
264One basic way is to try sending a REST API request that is handled by a MicroService. If the Orchestrator has been unable to make its connection, an error response will be returned to the REST client:
265
266 {"error": "MicroService connection is down"}
267
268A better way is to inspect what happened when you started each QEWD-Up instance. The following details apply for both co-located and separately-located MicroServices.
269
270When you first start the Orchestrator as a foreground process and look at its QEWD activity log within the terminal window, you'll see that it contains line like these:
271
272 Starting QEWD
273 Setting up micro-service connections
274 Adding MicroService Client connection: url = http://login_service:8080; application = login_service
275 starting microService connection to http://login_service:8080
276
277and it should finish with the lines:
278
279 ========================================================
280 ewd-qoper8 is up and running. Max worker pool size: 2
281 ========================================================
282 ========================================================
283 QEWD.js is listening on port 8080
284 ========================================================
285
286At this point, the *login_service* MicroService hasn't been started, so the *Orchestrator* will not have been able to connect to it. However, it is waiting for it to start and will automatically detect if/when it becomes available.
287
288
289Now let's start the *login_service* MicroService. If the networking and configuration details are correct, then you should see the following appear in the *Orchestrator* QEWD activity:
290
291 login_service registered
292 http://login_service:8080 micro-service ready
293
294Simultaneously, you should see something like the following in the *login_service* MicroService's QEWD activity:
295
296 Wed, 09 Jan 2019 13:48:28 GMT; worker 37 received message: {"type":"ewd-register","application":"login_service","jwt":true,"socketId":"CylKV170ui8jhkwRAAAA","ipAddress":"::ffff:172.18.0.2"}
297 **** jwtHandler encrypt: key = 28e672080cd693aaf3ffc725713911f97494a3b265cb399d73ba07ca478c778c
298 **** jwtHandler encrypt: iv = addb7057dece2deccf639973e9b96542
299 Wed, 09 Jan 2019 13:48:28 GMT; master process received response from worker 37: {"type":"ewd-register","finished":true,"message":{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NDcwNDIwMDgsImlhdCI6MTU0NzA0MTcwOCwiaXNzIjoicWV3ZC5qd3QiLCJhcHBsaWNhdGlvbiI6ImxvZ2luX3NlcnZpY2UiLCJ0aW1lb3V0IjozMDAsInFld2QiOiI5YTRhMTI4ODllOTg4OTJmY2VmZmU4OWZhM2NkNGRjNzE2MGEwNzk1ZDUwOWNjZTM3NTllYTAyNjViZjIyYmJkOGEzNzZjZTUyMzBmZjcyYTljZGI2NmUyYzY0NmMyOTRhMDg1MmU2ZmFhNDBiMTcxZTllZDNhN2U2MzJlMDg3Y2ZjZjAyODY2YTU1OTcwMDdlNmZjZGNhZWIzZTQ1MTZlNTk2YmE1ZDllNzRlZmQwZWU5YjRiYTk1ZTU5MDUxZjEifQ.sv1ycIfuUyNa55nwxhJFO3peUrT0G2zqewnBGYgHNOQ"}}
300
301What has happened is that the *Orchestrator* detected the *login_service* MicroService becoming available via its configured network connection, established a WebSocket connection to it and sent a registration message to it, In response to this, the *login_service* MicroService QEWD instance generated a JWT and returned it to the *orchestrator* as part of its registration response message.
302
303If you **didn't** see this activity on the *Orchestrator* and your MicroService instance, it means that there's something wrong with either the networking or the network configuration information in your *config.json* file.
304
305If you *do* see this activity, then the *Orchestrator* and *login_service* MicroService are now ready to inter-operate.
306
307## Stopping and Starting the QEWD-Up Instances
308
309The QEWD instances that make up your overall service can be stopped and restarted independently and in any sequence, and they will automatically re-connect and re-register with each other.
310
311You can try this out and see it working. First, stop the *login_service* MicroService instance whilst leaving the *Orchestrator running. You should see the following in the *Orchestrator's* QEWD Activity log:
312
313 *** server has disconnected socket, probably because it shut down
314
315Now restart the *login_service* MicroService instance. Once it has fully started and usually after a brief pause, the *Orchestrator's* QEWD Activity log should now show:
316
317 *** socketClient re-register - secret = a0477748-bcba-413c-bd33-e0674267e3f7
318 Re-registered
319
320In the *login_service* MicroService's QEWD Activity log you'll see the same registration message/response activity as before.
321
322Now, leaving the *login_service* MicroService running, see what happens when you stop the *Orchestrator*: you should see something like this appear in the *login_service* MicroService's QEWD Activity log:
323
324 socket sFVXjHr6Jl6wuVpFAAAA disconnected
325
326Now restart the *Orchestrator*. As soon as it is fully started, you'll see the *login_service* MicroService receive a registration request from the *Orchestrator* and the *Orchestrator's* activity log will show that the MicroService is ready for use.
327
328# Persisting Data in the Integrated YottaDB Database
329
330By default, any data that is created within the integrated YottaDB database within a Dockerised QEWD instance is lost when you shut it down.
331
332In order to persist such data between restarts of the QEWD instance, you must:
333
334- install and configure a pre-initialised copy of the YottaDB database files on your host machine
335- map the folder containing these YottaDB files to the internal folder where YottaDB within the Docker container expects to find these files
336
337## Installing the Pre-Initialised YottaDB Database Files
338
339We've already created a Github repository that contains the files you need. Just create a directory for them on your host machine and clone the files.
340
341For example, if we wanted to persist user authentication information that we might save within our *login_service* MicroService, we might create a directory for them on the Docker host machine using:
342
343 mkdir -p ~/yottadb/login_service
344
345The simplest way to clone the files we need from the Github repository is to use *subversion*. If you haven't already installed it:
346
347 sudo apt-get install subversion
348
349Then clone the pre-initialised YottaDB files using:
350
351 cd ~/yottadb
352 svn export https://github.com/robtweed/yotta-gbldir-files/trunk --depth files login_service
353
354**Note**: if you're using a Raspberry Pi, you need the compatible versions of the YottaDB files. Change the commands above to:
355
356 cd ~/yottadb
357 svn export https://github.com/robtweed/yotta-gbldir-files/trunk/rpi/r1.22 login_service
358
359
360You should now see the three files that will be used by YottaDB for persistent data storage in the *~/yottadb/login_service* directory.
361
362It's a good idea to ensure their permissions are set to allow the appropriate read/write access:
363
364 cd login_service
365 sudo chmod 666 *
366
367## Mapping the YottaDB Files at Startup
368
369Now you can start the *login_service* MicroService as follows:
370
371 docker run -it --name login_service --rm --net qewd-net -v ~/ms-db:/opt/qewd/mapped -v ~/yottadb/login_service:/root/.yottadb/r1.22_x86_64/g -e microservice="login_service" rtweed/qewd-server
372
373YottaDB within the QEWD Docker container will now read from and write to your host-sourced copies of its database files, and as a result, YottaDB data is persisted between restarts of the *login_service* MicroService.
374
375# Monitoring the QEWD Activity of your QEWD Docker Instances
376
377If you start the *orchestrator* and MicroServices as foreground processes (ie using the *-it* parameter), then you'll be able to view all the QEWD activity within the terminal window.
378
379However, if you start them as background daemon processes, then, of course, you can't see what's happening within them.
380
381**Note**: if you lose contact with the host machine's network for some reason, Docker processes started as foreground ones will continue to run, effectively as daemon processes.
382
383If you want to view the QEWD activity of a daemon QEWD process, you can use the *docker logs* command:
384
385 docker logs -f {Docker name}
386
387For example:
388
389 docker logs -f orchestrator
390
391or:
392
393 docker logs -f login_service
394
395
396# Using the *qewd-monitor* Application
397
398If you have exposed QEWD-Up's Web Server default listener port (8080) via a host port (using the -p parameter), then you can use the browser-based *qewd-monitor* application.
399
400So, for example, if the IP address of the host machine is *204.50.20.2*, and if you had started the *Orchestrator* using:
401
402 docker run -it --name orchestrator --rm --net qewd-net -p 3000:8080 -v ~/ms-db:/opt/qewd/mapped rtweed/qewd-server
403
404Then you could start its *qewd-monitor* application in a browser by using the following URL:
405
406 http://204.50.20.2:3000/qewd-monitor
407
408Similarly, if you'd started the *login_service* MicroService using:
409
410 docker run -it --name login_service --rm --net qewd-net -p 3001:8080 -v ~/ms-db:/opt/qewd/mapped -e microservice="login_service" rtweed/qewd-server
411
412Then you could start its *qewd-monitor* application in a browser by using the following URL:
413
414 http://204.50.20.2:3001/qewd-monitor
415
416You'll need to enter the QEWD management password which has been set by default as:
417
418 keepThisSecret!
419
420It is recommended that you change this password. This is done within your *config.json* file by setting the *qewd.managementPassword* property for the *Orchestrator* and each MicroService. For example:
421
422 {
423 "qewd_up": true,
424 "orchestrator": {
425 "qewd": {
426 "serverName": "Orchestrator",
427 "managementPassword": "myOrchestratorPassword"
428 }
429 },
430 "microservices": [
431 {
432 "name": "login_service",
433 "qewd": {
434 "serverName": "Login MicroService",
435 "managementPassword": "myLoginServicePassword"
436 }
437 }
438 ]
439 }
440
441It's up to you what to specify as the password, but, as you have now made the *qewd-monitor* application publicly accessible, and because it allows the QEWD instance to be shut down and any persistent data to be viewable, you should choose a suitably cryptic password.
442
443
444When you log in to the *qewd-monitor* application, the Overview panel will appear, showing configuration information and the activity in the QEWD Master and Worker processes.
445
446Clicking the red *X* buttons next to the Master and Worker processes will stop them. It is always quite safe to stop the Worker processes at any time - QEWD will automatically restart them as demand requires. You'll always see at least one Worker process in the Overview panel, even if you shut them all down - because *qewd-monitor* requires access to a Worker process in order to display the information you're viewing. Stopping the Worker processes is a quick and simple way to ensure that you're using the latest API handler methods during development (API handler methods always run in QEWD Worker processes, and Node.js caches them).
447
448Stopping the Master process within the *qewd-monitor* application will stop the Docker instance. This is the cleanest way to stop a QEWD instance, ensuring that the connections to YottaDB are cleanly shut down before the Docker instance stops.
449
450Click the *Document Store* tab in the top banner and you should see two Persistent JSON Documents named *Documents* and *DocumentsIndex*. Click on them to drill down into their structure.
451