Will PCF run the Tomcat embedded in Spring boot jar or it runs its own tomcat. In PCF we never mention the port number. In the classic approach, we start 3 Tomcat instances in different port number and have apache server before that. Does PCF work the same way.
This is a pretty broad question, so I'm going to answer with a pretty broad response but link you to where you can find more details, if you are inclined to dig in more.
How PCF works internally when deploying Spring boot project
Will PCF run the Tomcat embedded in Spring boot jar or it runs its own tomcat.
When you run cf push -p my/cool/file.jar (or even file.war), the cf cli extracts everything from that archive and pushes it up to CF. CF stores your app files & then your app is staged.
During staging, the Java build pack runs. It looks at all the files that were pushed & tries to determine what to do with them. It knows how to handle several different types of apps [1], including both standard WAR files & Spring Boot apps. The build pack will check your app to see if its one of the supported types in order [2] and will select the first match.
After selecting the type of app, it runs through and installs what is necessary to run your app. For a Spring Boot app, that's basically just the JVM. For a WAR file, it installs Tomcat & a JVM. In addition, it writes out the configuration & start up commands necessary for CF to launch your app.
At this point staging is complete and you have what is called a "droplet". If you have any additional questions on the staging workflow, read here for more details [3].
At this point, the app would be started. The platform takes the droplet that was created and executes the command specified by the build pack to start the app [4]. If all goes well, your app will then be up and running on CF.
In PCF we never mention the port number.
Correct. The platform will tell you the port on which your application should listen. For Java apps, you don't have to do anything. The Java buildpack will handle configuring Spring Boot or Tomcat to start and listen on the correct port.
For Spring Boot apps, you can look at the start up command to see how it's doing this. For Tomcat, it happens in the server.xml that's generated by the Java buildpack [5].
In the classic approach, we start 3 Tomcat instances in different port number and have apache server before that. Does PCF work the same way.
Yes and no. Each application you run can have multiple instances. If you scaled your app to have three instances, that would be roughly like having 3 Tomcat instances in your classic approach.
The main difference is that there would be no Apache Web Server in front. On Cloud Foundry, this is not necessary because it has it's own load balancer called Gorouter [6] which handles proxying traffic to your app and load balancing across available app instances.
This is a classic mistake that people new to CF make. They try to replicate classic architectures and shoehorn a reverse proxy into their app when it's not necessary. This is one of the benefits of CF. It handles routing traffic to your app in a scalable way, freeing you up to focus more on your app.
[1] See "Standard Containers -> https://github.com/cloudfoundry/java-buildpack#additional-documentation
[2] https://github.com/cloudfoundry/java-buildpack/blob/master/config/components.yml#L18
[3] https://docs.cloudfoundry.org/concepts/how-applications-are-staged.html
[4] https://docs.cloudfoundry.org/concepts/overview.html#apps-anywhere
[5] https://github.com/cloudfoundry/java-buildpack/blob/master/resources/tomcat/conf/server.xml#L21
[6] https://docs.cloudfoundry.org/concepts/architecture/#routing
No. The simple answer is each instance of ur application jar is running in its own container within PCF. So there is no clash of using the same port numbers.
Related
I am creating a spring boot microservice project with intelij IDEA.
Currently I have developed three seperate spring boot rest services as customer service, vehicle service and spring cloud config server. Spring cloud config server is pointing to a github repository.
The issue is sometimes above projects take more than 10 minutes to run and sometimes does't run and give an error message as "failed to check application readystate intellij attached provider for the vm is not found". I have no idea why this happens ?
There are two possible causes:
1. IntelliJ IDEA and the Spring application are running in different JVMs.
There is a bug for IntelliJ IDEA regarding that:
https://youtrack.jetbrains.com/issue/IDEA-210665
Here is short summary:
IntelliJ IDEA uses local JMX connector for retrieving Spring Boot actuator endpoint's data by default. However, it could be impossible to get local JMX connector address via attach api if Spring Boot application and IntelliJ IDEA are run by different JVMs. In this case, add the following lines to VM options of your Spring Boot run configuration:
-Dcom.sun.management.jmxremote.port={some_port}
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
As mentioned in the official Oracle documentation, this configuration is insecure. Any remote user who knows (or guesses) your port number and host name will be able to monitor and control your Java applications and platform.
2. Prolonged time to retrieve local hostname
You can check that time using inetTester. Normally it should take only several milliseconds to complete. If it takes a long time then you can add the hostname returned by inetTester to /etc/hosts file like this:
127.0.0.1 localhost winsky
::1 localhost winsky
I have two docker instances that I launch with docker-compose.
One holds a Cassandra instance
One holds a Spring Boot application that tries to connect to that application.
However, the Spring Boot application will always fail, because it's trying to connect to a Cassandra instance that is not ready yet to take connections.
I have tried:
Using restart:always in Docker-compose
This still doesn't always work, because the Cassandra might be up 'enough' to no longer crash the Spring Boot application, but not up 'enough' to have successfully created the Table/Column family. On top of that, this is a very hacky solution.
Using healthcheck
It seems like healthcheck in compose doesn't have restart capabilities
Using a bash script as entrypoint
In the hope that I could use netstat,ping,... whatever to determine that readiness state of Cassandra
Right now the only thing that really works is using that same bash script and sleep the process for x seconds, then start the jar. This is even more hacky...
Does anyone have an idea on how to solve this?
Thanks!
Does the spring boot service defined in the docker-compose.yml depends_on the cassandara service? If yes then the service is started only if the cassandra service is ready.
https://docs.docker.com/compose/compose-file/#depends_on
Take a look at this github repository, to find a healthcheck for the cassandra service.
https://github.com/docker-library/healthcheck
CONCLUSION
After some discussion we found out that docker-compose seems not to provide a functionality for waiting until services are up and healthy, such as Kubernetes and Openshift provide (See comments below). They recommend to use wrapper script (docker-entrypoint.sh) which waits for the depending service to come up, which make binaries necessary, the actual service shouldn't use such as the cassandra client binary. Additionally the service depending on cassandra could never get up if cassandra doesn't, which shouldn't happen.
A main thing with microservices is that they have to be resilient for failures and are not supposed to die or not to come up if a depending service is currently not available or unexpectedly disappears. Therefore the microservice should be implemented in a way so that it retries to get connection after startup or an unexpected disappearance. Unexpected is a word actually wrongly used in this context, because you should always expect such issues in a distributed environment, and even with docker-compose you will face issues like that as discussed in this topic.
The following link points to a tutorial which helped to integrate cassandra properly into a spring boot application. It provides a way to implement the retrieval of a cassandra connection with a retry behavior, therefore the service is resilient to a non existing cassandra database and will not fail to start anymore. Hope this helps others as well.
https://dzone.com/articles/containerising-a-spring-data-cassandra-application
I am a newbie with CF microservices and I am trying to deploy a service multiple times. As far as I understood, each time I deploy into a space the application is getting a different database server and schema. Is there a way to tell the Cloud Foundry to use only a fixed DB server all the times across multiple deployments in one environment?
The keyword for your case is 'Service Instance'
You can create a service instance of database server within the environment specific for your application and bind it via application manifest.
e.g.
cf create-service rabbitmq small-plan myapplication-rabbitmq-instance
As long as you have a binding to myapplication-rabbitmq-instance in your application manifest it would be preserved/be the same between application deployments within this space.
e.g. in your application manifest:
---
...
services:
- myapplication-rabbitmq-instance
More on https://docs.cloudfoundry.org/devguide/services/
I'm evaluating options for my team's middleware. We really have a frankenstein'd setup. We're using Apache ServiceMix(Karaf/ActiveMQ/CXF), Websphere 8.5, ActiveMQ where we don't really need it, and all of our applications are not really coded to failover to another node if the primary goes down. We realized the issues of our setup and now want to improve.
We currently host bundles (not sure if they're all OSGI compliant) in a Karaf Container, which are used via ActiveMQ after being sent JMS messages via Apache Camel from Websphere.
My current idea is to kill off ActiveMQ, make all the camel routes towards HTTP (instead of JMS queues), and convert our data bundles/services to serve via HTTP through Apache CXF (replacing websphere for some things) and not ActiveMQ Queues/JMS. However, we have Websphere licenses, and I do know that it supports bundles in some way, I'm just not as familiar as to how it does (same nature as karaf)?
The main question is in the title, and I hope it's not too generic.
WebSphere 8.5 is a full OSGi container supporting Blueprint just as Karaf does.
You can, in theory, run your camel bundles or whatnot just as fine in WAS8.5. However, Apache Karaf is a lot more aligned towards running ActiveMQ/CXF/Camel stuff than WebSphere will ever be. Installation in Karaf is a few commands, where installation and configuration struggle in WAS85 for the Camel feauters and basic camel routes is .. well, a headace when I tried it last time. Others seems to have the same struggle.
I have rather good experience of running Camel apps inside WebSphere Application Server, but that was by embedding Camel in a standard WebApp, not using the OSGi stuff. So, embedded web apps is my recommendation for running Camel inside WebSphere.
For the "replace AMQ/JMS with HTTP" part. You are aware of that you are replacing pears with apples, right? JMS has a lot of features HTTP does not have (and some overhead compared to HTTP). For the sake of completeness, WebSphere also has a JMS provider built in. So if you have a large HA secured WebSphere infrastructure, the WebSphere (SIBus) provider might be a good choice. Otherwise, ActiveMQ rocks :-)
Can a Worklight Server be deployed to a WebSphere application server which also runs other non-Worklight .ear applications? Or does Worklight need its own separate instance of WAS?
Just like you can deploy multiple instances of Worklight (v6 and above) projects - multiple .war files to the same WAS application server, there should not be issues to deploy it to an application server running other services.
That said, possible issues to consider:
When deploying a Worklight project, you will want to enable "application security"
(in the WAS admin console, Security > Global Security). If there are some other web
applications for which application security is undesired, you need a different WAS server
instance.
Setting up, enabling and migrating security
The list of users that can use the web applications are configured through LDAP or
"federated repositories", or similar. If, for Worklight, you need to use a completely
different set of user logins than for the other web applications, then you need to use
multiple "security domains".
Configuring multiple security domains
The machine hosting the application server will probably need memory upgrades...
Deploying the Enterprise Archive (EAR) Using the WebSphere Admin Console
Probably also need to make clear seperation where required:
IBM WebSphere Developer Technical Journal: Co-hosting multiple versions of J2EE applications
Worklight is itself an application running inside a web container, whether that be Tomcat, WAS Liberty, or full WAS. It's essentially a layer running underneath the container to handle requests for Worklight applications, fielding their context root requests. If you create the WAR file for your Worklight app and extract out the deployment descriptor you'll find all the necessary filters and listeners that most other apps would have.
Things like adapters and wlapps are "installed" to this underlying layer, and are merely extracted and stored as whatever was packaged with them, such as the JS and CSS you used to make you app. In fact, with a standard Liberty install you can typically find your adapters in plain sight at (for the WL5.0.6 instance I have handy, it's different for WL6):
/opt/IBM/Worklight/server/wlp/usr/servers/worklightServer/worklight.home/worklight/data/export/adapters
So, in addition to what Idan has said, I also present you with the following docs (assuming WL6)
Overview of the Worklight Server installation process
Given my own experience, you should be perfectly able to install other EAR and WAR files to your existing WAS instance, just make sure your context roots are unique, as always ;)
I also second the memory considerations.