I have a node.js app running in Azure as a webApp. On startup it connects to an external service using a websocket subscription. Specifically I'm using the reconnecting-websockets NPM package to wrap it to handle disconnects.
The problem I am having is that because there are 2 instances of the app running on Azure (horizontal scaling for failover) I end up with two subscriptions at any one time.
Is there an obvious way to solve this problem?
For extra context, this is a problem for 2 reasons:
I pay for each message received and am over quota
When messages are received I process then and do database updates, these are also being duplicated.
You basically want to have an AppService with potentially multiple instances, but you don't want your application to run in parallel. At least you don't want two have two subscriptions. Ideally you don't want to touch your application code.
An easy way to implement this would be to wrap your application into a continuous WebJob, and set its scale property to singleton.
Here is one tutorial on how to set up a nodejs webjob: https://morshemesh.medium.com/continuous-deployment-of-web-jobs-with-node-js-2308f95e63b1
You can then use a settings.job file to control that your webjob only runs on a single instance at any one time. Or you can use the Azure Portal to set the value when you manually deploy the Webjob.
{
"is_singleton": true
}
https://github.com/projectkudu/kudu/wiki/WebJobs-API#set-a-continuous-job-as-singleton
PS: Don't forget to enable Always On. It is also mentioned in the docs. But you probably already need that for your current deployment.
If you don't want your subscription to be duplicated then it stands to reason that you only want one process subscribing to the external websocket connection.
Since you mentioned that messages received will be updated in the db, then it makes sense that this would be an isolated backend process since you made it clear that you have multiple instances running for the frontend server (and whether or not a separate backend).
Of course if you want more redundancy, you could use a load balancer with simple distribution of messages to any number of instances behind. Perhaps some persistent queueing system if you feel that it's needed.
If you want these messages to be propagated to the client (not clear from the question), this will be a bit more annoying. If it's a one-way simple channel, then you could consider using SSE which is a rather simple protocol. If it's bilateral then I would myself probably consider running a STOMP server with intermediary broker (like RabbitMq) and connect directly from the client (i.e. the browser, not the server generating the frontend) to the service.
Not sure if you're well versed with Java, but I made some app that you could use for reference in case interested when we had to prepare some internal demos: https://github.com/kimgysen/zwoop-backend/tree/develop/stomp-api/src/main/java/be/zwoop
For all intents and purposes, I'm not sure if all this is worth the hustle for you, it sounds like you're on a tight budget and that you're looking for simple solutions without too much complexity. Have you considered giving up on load balancing the website (is the load really that high?), I don't have enough background knowledge on your project to judge, I believe. But proper caching optimization and initially scaling vertically may be sufficient at the start (?).
Personally I would start simple and gradually increase complexity when needed.
I'm just throwing ideas at you, hopefully it is helpful in any way to have a few considerations.
Btw, I don't understand why other answers on this question were all deleted (?).
Related
I'm currently working on a new google polymer web application and wondered if I should use firebase as the backend/db. I took a look at the project, made some test applications and really liked it! But to fully convince me, that firebase is the way to go I need the following questions answered:
I'm a little bit concerned about security: So, I know, that firebase uses read, write and validate to implement server side security. From the samples, I noticed that the validation basically is a one-line JS script, that represents a 'if'. As I'm planning to build a web e-commerce application I need to validate quite some inputs. Is there a possibility, to outsource the validation in a separate file, to make it more readable? Also I wondered, if there is a possibility, to test these server side validations, with for example unit tests?
I'm not 100% sure at the moment, that firebase can cover all of our use cases. Would it be possible/a good solution to use a "normal" backend for some critical functions and then persist the data from the backend in firebase?
I saw some nice polymer elements for firebase. Is firebase 100% supported in polymer/web components?
Is there an other way (like Java approach) to implement server business logic?
Is there a way, to define update scripts, so that new releases can easily be pushed to production?
Thanks & kind regards
Marc
So, I asked the firebase supprt and got the following answer:
Great to meet you.
I'm a little bit concerned about security: So, I know, that firebase uses read, write and validate to implement server side security. From the samples, I noticed that the validation basically is a one-line JS script, that represents a 'if'. As I'm planning to build a web e-commerce application I need to validate quite some inputs. Is there a possibility, to outsource the validation in a separate file, to make it more readable? Also I wondered, if there is a possibility, to test these server side validations, with for example unit tests?
You can implement extremely complex and effective rules using our security rules language. You can deploy security rules as part of your hosting deploy process, or via the REST API. It's not possible to break the contents into multiple files on the server, but you could certainly build your own process for merging multiple files into a single JSON result.
I'm not 100% sure at the moment, that firebase can cover all of our use cases. Would it be possible/a good solution to use a "normal" backend for some critical functions and then persist the data from the backend in firebase?
Generally speaking, synchronizing Firebase and a SQL back end is not very practical and they don't translate well. It's probably entirely redundant as well.
I saw some nice polymer elements for firebase. Is firebase 100% supported in polymer/web components?
I don't know what 100% supported means in this context. We offer a JavaScript SDK so they should play fine together.
Is there an other way (like Java approach) to implement server business logic?
We offer official SDKs in Java, Objective-C/Swift, Android, Node.js, JavaScript, and a REST API for use with other languages.
Is there a way, to define update scripts, so that new releases can easily be pushed to production?
I'm not sure what this means. Most likely the answer is no, since we don't provide a build process or any tools to release your software.
I hope that helps!
I responded:
Thank you for the information, it helped me very much! After reading your response on question number 5 one further question popped into my mind:
…
5. Is there a way, to define update scripts, so that new releases can easily be pushed to production?
I'm not sure what this means. Most likely the answer is no, since we don't provide a build process or any tools to release your software.
Is there like a best practice on how to handle the database schema? I only have one web application (without apps, etc.) in my case... I expect, that the database will change drastically over time and releases. Should I write JS logic, that checks the current database version and update it, if it's necessary? Maybe this would make a nice feature...
For example: I deployed Version 1.0 of my application and everything works fine. After 3 months of programming I notice, that the user data needs a further attribute: address, which is a 'not null' attribute. I now deploy Version 2.0 of my application and every new registered user has a address, but the old users (from Version 1.0) do not have this field or a value.
How should I handle this?
Support responded:
Hi Marc,
There’s no best practice here, but your ideas seem fairly sound. You probably don’t need to check in your JavaScript. You can probably store a version number in the user’s profiles, and when they upgrade to the latest software, you can upgrade that in their profile data.
Then your validation rules could use something like the following:
{
"user": {
".write": "newData.hasChild('address') || newData.child('appVersion') < 4",
"address": {
".validate": "newData.isString() && newData.val().length < 1000"
}
}
}
So if you are concerned about versioning, this could be used to deal with legacy releases.
Another popular approach I’ve seen from devs is to do intermediate upgrades by duplicating data. Thus, you release an intermediate version that writes to the old path and to the new path with the updated data structure (which keeps the app working for old users till they upgrade). Once a reasonable percent of clients are upgraded, then release a final version that no longer does a dual write to the old structure and newer structure.
Of course, flattening data, while it makes joining and fetching data bit more of a pain, will make upgrades much easier as the modular data structure adapts more easily to changes. And, naturally, a pragmatic design where you wrap the various records in a class (e.g. the UserProfile class with getter/setter methods) makes transitions simpler as you can easily hack in versioning at one place.
Hope this helps someone :)
Has anyone an idea for the following scenario?
I have a RIA-Webapplication (realized in ExtJs). What I want to implement is the possibility to use local ressources like card readers or fingerprint readers or other serial devices and filesystem access.
I thought about implementing this with a local websocket service which has to be installed by our customer before using our RIA the first time. When the webapp is loading it should scan the local machine if a websocket service is available and connect to it.
After that, local events (like new card is beeing read or recognized new finger) should be passed to the browser via websocket connection.
Any ideas how to get started with such a solution?
I have made something like that. Besides the obvious things such as read/write/poll data from the card-readers and so on, you would have to either implement everything yourself or, use a library for technology you are going to employ for your web-server. So, if you use a LAMP solution, i think there are some web-socket libraries for PHP that you can use. However, if you do everything by yourself then you have to implement everything from hand-shaking, to creating data packets. I have done everything from scratch by using .NET and it provides a number of useful libraries such as hashing. Java also would be a good option and have those kind of libraries as well. In general if you doing everything by yourself i would say the trickiest thing would be to split the data you want to transmit among various data packet. It is not that hard to do things from scratch. The RFC (https://www.rfc-editor.org/rfc/rfc6455) helped me a lot. Hopefully, this helps.
How can I save the application state for a node.js Application that consists mostly of HTTP request?
I have a script in Node.JS that works with a RESTful API to import a large number (10,000+) of products into an E-Commerce application. The API has a limit on the amount of requests that can be made and we are staring to brush up against that limit. On a previous run the script exited with a Error: connect ETIMEDOUT probably due to exceeding API limits. I would like to be able to try connecting 5 times and if that fails resume after an hour when the limit has been restored.
It would also be beneficial to save the progress throughout in case of a crash (power goes down, network crashes etc). And be able to resume the script from the point it left off.
I know that Node.js operates as a giant event-queue, all http requests and their callbacks get put into that queue (together with some other events). This makes it a prime target for saving the state of current execution. Other pleasant (not totally necessary for this project) would be being able to distribute the work among several machines on different networks to increase throughput.
So is there an existing way to do it? A framework perhaps? Or do I need to implement this myself, in that case, any useful resources on how this can be done would be appreciated.
I'm not sure what you mean when you say
I know that Node.js operates as a giant event-queue, all http requests and their callbacks get put into that queue (together with some other events). This makes it a prime target for saving the state of current execution
Please feel free to comment or expound on this if you find it relevant to the answer.
That said, if you're simply looking for a persistence mechanism for this particular task, I might recommend Redis, for a few reasons:
It allows atomic operations on many data types; for example, if you had an entry in Redis called num_requests_made that represented the number of requests made, you could increment this number easily in Redis using INCR num_requests_made, and it's guaranteed to be atomic, making it easier to scale to multiple workers.
It has several data types that could prove useful for your needs; for example, a simple string could represent the number of API requests made during a certain period of time (as in the previous bullet point); you might store details on failed API request that need to be resubmitted in a list; etc.
It provides pub/sub mechanisms which would allow you to communicate easily between multiple instances of the program.
If this sounds interesting or useful and you're not already familiar with Redis, I highly recommend trying out the interactive tutorial, which introduces you to a few data types and commands for them. Another good piece of reading material is A fifteen minute introduction to Redis data types.
I'm trying to build a phonegap app for ios and android. It's been going well so far but now I hit a major obstacle and I need some help.
I need to connect to a remote Postgres database. I haven't done anything like that before.
Does anyone have any experience/tips for this, or know of any resources which contain relevant information?
From client-side javascript, you can't. Unless phonegap has done something very odd with permissions or provided a PostgreSQL interface (which presumably you'd know about if they had).
What you'll want to do is provide a small server-side wrapper to PostgreSQL that will take requests, convert them to queries and return (presumably) json-formatted results. Oh - and you'll need to think about security too - who can connect, what can they do, does it all need to be encrypted?
If your requirements are simple, this can be easy enough to do in Perl/Python/Ruby etc. or even javascript if you have node.js to hand. With Perl you'd wrap DBIx::Class in a Dancer app - similar modules exist for all the above scripting languages.
Do consider whether you want to run the whole thing over https (let apache handle this for you) - it will avoid issues with passwords/private data being sniffed over wireless connections.
For example, your app would issue an ajax request to: http://myserver/projects/123/messages?limit=20&sort=date
That would be translated into a query into the project-messages table for the last 20 messages sorted by date and wrap the results up as an array of JSON objects (presumably).
You would need to create an API for your data. Then access that API using promises from your js app.
To let the security issues where they belong to (in existing experienced and tested parts of server / client software) and to have a minimum effort of development, I suggest to use some existing lightweight middle ware:
http://restsql.org/doc/Overview.html
It comes with a docker, where any service you require is packed in, thus making it easy to try it out quickly.
This is more of a curiosity really, to see if some one has done anything similar, or if at all it is possible.
I'm working on a project that will get notification through external notifications. Now I could go about doing this by having notifications coming to my server and have a comet setup between my client and server.
BUT
I was wondering if I could write server logic into my client and listen out for notifications from external sources. Immediately one issue I see is, external sources would need callback URL etc, which I dont know if you could do from client side (unless one could use the IP address in that way).
As you can see it is more ideas and discussions if such a thing was possible, this is somewhat inspired by P2P models whereby you wouldn't be mediating things through your central server.
Thanks in advance!
GWT compiles (nearly) Java source into JavaScript, so compiled GWT apps can't do anything that traditional JavaScript running in the browser cannot do. The major advantage of bringing Java into the picture isn't automatic access to any/all JVM classes, but the ability to not only maintain Java sources, which tend to be easier to refactor and test as well as keep consistent with the server, and to compile that statically defined code into JavaScript, performing all kinds of optimizations at compile time that aren't possible for normal JavaScript.
So no, while you can have some code shared by the client (in a browser) and the server (running in a JVM), you can't run Tomcat/Jetty/etc in the browser just by using GWT to compile the java code into JS.
As you point out, even if this was possible, it would be difficult to get different clients to talk back and forth, without also requiring that the browsers can see and connect at will to one another. BitTorrent and Skype have different ways for facilitating this, and currently browsers do not allow anything like this - they are designed to make connections to other servers, not to allow connections to be made to them.
Push notifications from the web server to the browser are probably the best way forward, either through wrapping comet or the like, or through an existing GWT library like Atmosphere (see https://github.com/Atmosphere/atmosphere/tree/master/samples/gwt-demo for a demo).