How to specify the statsd client port? - java

I have one java spring boot application deployed on pcf environment. I have used statsd client library to send metrics to the statsd server. So the problem is how do I specify host and port in statsd client so that it can send metrics.
public StatsDClient statsDClient(
#Value("${metrics.statsd.host:localhost}") String host,
#Value("${metrics.statsd.port:8125}") int port,
#Value("${metrics.prefix:example.app}") String prefix
) {
return new NonBlockingStatsDClient(prefix, host, port);
}
I have to specify the host and port for the PCF deployed app, How to do it ?

If I am understanding it correctly you have two apps running in PCF.
One Spring boot app- which you are calling some client app.
Second is your statsd server
and you need to establish a communication between these two.
As Daniel mentioned in comment you have two ways to do it.
HTTP/TCP
Internal Route
Problem with option 1 is that you may not be able to use that with host and port separately as PCF internally doing that.
I'd recommended to use the second option- Internal route which gives you clear host name and port which you need to configure in client app.
Here are the steps you can follow to configure the Container-to-Container networking
Add a new route to your server app -i.e. app1.apps.internal
Create network policy with client and server app - link
Define property in config server or code-base whatever process you are using for property externalization - Your final URL would look like: app1.apps.internal:8080

Related

Why do we use port number localhost: 8080? Why don't we use a port number when using www.example.com?

When I use a Spring Boot app in local it uses, localhost:8080. When it is pushed to Pivotal Cloud Foundry, it has some route https://my-app.xyz-domain.com and we can access the URL without a port, what is happening behind the scene?
Please help me understand.
There is a default port number for each protocol which is used by the browser if none is specified. For https it is 443, for http 80 and for telnet 23.
On Unix and similar systems like Linux, those are often not available to a developer so other ports are used but then they have to be specified. 8080 is often available and looks like 80.
On CloudFoundry, your application is actually still running on localhost:8080. The reason that you can access your application through https://my-app.xyz-domain.com is that the platform handles routing the traffic from that URL to your application.
The way this works is as follows:
You deploy your application. It's run by the foundation in a container. The container is assigned a port, which it provides to the application through the $PORT env variable (this can technically change, but it's been 8080 for a long time). Your application then listens on localhost:$PORT or effectively localhost:8080.
The platform also runs Envoy in your container. It's configured to listen for incoming HTTP and HTTPS requests, and it will proxy that traffic to your application on localhost:$PORT.
Using the cf cli, you map a route to your application. This is a logical rule that tells the platform what external traffic should go to your application. A route can consist of a hostname, domain, and/or path. For example, my-cool-app.example.com or my-cool-app.example.com/foo. For a route to work, the domain must have its DNS directed to the platform.
When an end-user accesses the route that you mapped, the DNS resolves to the platform and the traffic is directed to the external load balancers (sometimes TCP/layer4, sometimes HTTPS/layer7) that sit in front of the platform. These proxies do not have knowledge of CF, they just proxy incoming traffic.
Traffic from the external load balancers is spread across the set of the platform Gorouters. The Gorouter is a second layer of proxies, but these proxies have knowledge of the platform, specifically, all of the routes that have been mapped on the platform and where those applications actually live.
When a request comes to Gorouter, it will recognize the route like my-cool-app.example.com and look up the location of the container where that app is running. Traffic from Gorouter is then proxied to the Envoy which is running in the app container. This ties into step two as the Envoy will route that traffic to your application.
All in total, incoming requests are routed like this:
Client/Browser -> External LBs -> Gorouters -> Envoy -> Application
First, you should change the port to 80 or 443, because HTTP corresponds to 80, and HTTPS corresponds to 443. Then, you should set the domain name to resolve to the current host, so that you can access the current application through the domain name. In addition, if you want to set the local domain name, then The hosts file should be modified.

Run Spring Boot application on multiple server address

Just curious about this!!I have a spring boot application running on 10.0.0.1(9000 port) and same instance has a subnet for 10.0.0.2 The application is running on pid P1, How can I bind my Spring boot application to both the server address which must point to same process P1 and on same port 9000
10.0.0.1:9000/api
10.0.0.2:9000/api
The application must be accessible on both the server address without using create the new instance or new port,
I have tried using reverse proxy and proxy but still no luck,Is possible to do ?
https://access.redhat.com/solutions/873953 Looking something similar to this in Spring.
First way: find it on 0.0.0.0 which will then be available on all ip addresses.
Second way: Use a reverse proxy like nginx which listens on 10.0.0.2:9000 and forwards to your spring. (you mentioned it does not work. could you please give more details?)
Third way: let your spring listen on another port, say 8888. then use nginx to listen on both 10.0.0.1 and 10.0.0.2 and forward. Actually in production environment this is also very common (placing a reverse proxy before actual workload).

How to setup eureka clients behind reverse proxy with different port?

I am currently trying to setup service discovery with eureka, but the clients register with the wrong port. Every Eureka client is on a different server behind its own nginx reverse proxy and it is reachable from outside via https on port 443, but the java eureka clients are configured on different port. I also tried configuring them on the same port as nginx exposes, but than the nginx server has infinited redirects and stops after some attempts with error "invalid redirect". Being on different port the eureka clients register at the server with the port configure in spring boot yaml server port config. If then a client tries to reach another client it uses the port configured in the spring boot application. I need to be able to register the eureka client on a different port than I am running the client. Is that possible? What am I missing here? Would be using Zuul as a gateway make a difference here?
Setup (every system is deployed on a different VServer behind NGINX reverse proxy):
Eureka Server
Multiple Eureka Clients (API, UI, etc)
Identity Management Keycloak SSO server not registered with eureka server
A port can only be used by one service at a time. Hence, you cannot configure nignx and spring boot to listen on the same port and receive the error message.
Spring boot does not know about the proxy setup and hence the eureka client registers the instance (with the spring.port) at the eureka server. You can configure the eurka instance with the EurekaInstanceConfig. In this case you want to change eureka.instance.port=443 to the one exposed by nginx.

CloudFoundry websocket failed: Establishing a tunnel via proxy server failed

Note: I am not using Pivotal CF.
I have a java application deployed on CloudFoundry. I am using embedded Jetty to host my Jersey REST API. This API is by default exposed on port 8080 by cloud foundry.
My application also needs some websockets to stream data to the browser. I am using Java-WebSocket (https://github.com/TooTallNate/Java-WebSocket) for this. On my local machine, I was using port 8887 for my websocket connection. Everything worked fine.
After deploying on CloudFoundry, I can access my REST API but not my websocket. After searching a bit online, I found that websocket connections are only allowed on port 4443 (http://docs.run.pivotal.io/release-notes/)
I changed my server side to reflect this
import org.java_websocket.server.WebSocketServer;
public class MyWebSocket extends WebSocketServer {
public MyWebSocket() throws UnknownHostException {
super(new InetSocketAddress(4443));
}
#Override
public void onOpen(org.java_websocket.WebSocket websocket, ClientHandshake handshake) {
// Handle this
}
}
On my client side, I am connecting the websocket using the following
wss://my_cf_app.com:4443/
But I am getting the following exception.
WebSocket connection to 'wss://my_cf_app.com:4443/' failed:
Establishing a tunnel via proxy server failed
I also tried to connect the websocket on server side using "PORT" environment variable of CF but I get "Address already in use" error in Java-WebSocket.
I have tried many different things but I am unable to figure this out. Any help would be awesome.
After deploying on CloudFoundry, I can access my REST API but not my websocket. After searching a bit online, I found that websocket connections are only allowed on port 4443 (http://docs.run.pivotal.io/release-notes/)
Port 4443 is specific to Pivotal Web Services (and some installs of CF that run on AWS). Most PCF installs do not have a separate port for WSS, but just use 443 along with the HTTPS traffic. The port used ultimately depends on the load balancer being used in front of the CF installation and what it supports.
You would never have your application listen on port 4443. Port 4443 is the external port for traffic where the load balancer listens. This traffic will be directed to the port assigned to your application, which is $PORT (env variable).
I also tried to connect the websocket on server side using "PORT" environment variable of CF but I get "Address already in use" error in Java-WebSocket.
This is the correct behavior, i.e. you should be listening on the port assigned through $PORT env variable. What the error is telling you is that something is already listening on this port and you cannot have two things listening on the same port.
There is only one port available per application at this time (likely to change in the future). For now, if you have two separate applications listening on two separate ports then you need to push them to CF as two separate applications.
What you can do to make them appear like one application to end users is to map each one to a specific path. See the --route-path argument of cf push or docs for cf create-route.
https://docs.cloudfoundry.org/devguide/deploy-apps/routes-domains.html#create-route

Using same port for Server and remote JMX beans

We are using Embedded Jetty as our webserver running on port 8080 and want to monitor the application on Jconsole. We are using the following system property when starting the Jetty server specific to JMX:
-Dcom.sun.management.jmxremote.access.file=jmxremote.access
-Dcom.sun.management.jmxremote.password.file=jmxremote.password
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=8081
Although, JMX and Webserver are running on two different ports, is there a way for client to access JMX via Jconsole/JvisualVM using port 8080? Is JMX Proxy going to help me in anyway? Is it possible in any way?
Thanks in advance.
Ajay
Not without some effort. In a nutshell, there can always only be a single server on one port (or the other way around: Servers can't share a port).
If JMX was supporting HTTP requests, then you could run it as a servlet on the same HTTP server. There would be one port (used by the HTTP server) and then the HTTP URLs would allow the server to determine whether the client wanted to talk to JMX or the web application.
But JMX doesn't support HTTP requests directly. You can try Jolokia (see this question) or you can write servlets which allows a client to query certain mbeans (but without JMX protocol).
JMX specification have Connector that can use any protocol as transport, see http://en.wikipedia.org/wiki/File:Jmxarchitecture.png

Categories