Im running Java/Spring application with a Angular6 frontend. Within the Spring backend I calling another API thru http. but its around 6x slower than expected to get at response...
Isolating the API-call I get:
Locally running the same setup (Spring, Tomcat 8.5) from my dev-machine: 10-12 sec
Locally thru Postman: 10-12 sec
locally thru cUrl: 10-12 sec
Using cUrl from the console on the AWS EC2 instance 10-12sec.
Calling as intended (Spring running in Tomcat) on the AWS EC2 instance: 60-75sec.
Tried to change the Native Spring http (ResponseEntity postForEntity) call to OkHttp with no change in the result. The Api request and response is a tiny Json-string but the APi is slow so response times around 10 sec is normal.
As it seems to be something wrong with the Tomcat or java on the EC2. Can it be some parameters that I missed? or what else can i try to isolate and solve the problem?
The amount of data sent and revived is trivial (sending ~350 bytes, receiving less than that)
Its just the call to the API that takes a long time.
logger.debug("CallApi start");
start = System.currentTimeMillis();
try {
ObjectMapper mapper = new ObjectMapper();
String s = mapper.writeValueAsString(apiCalcDTO.getInput());
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(120, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS)
.build();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, body);
Request request = new Request.Builder()
.url("http://www.example.com/api/1.0/xxx")
.post(body)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.addHeader("cache-control", "no-cache")
.build();
Response response = client.newCall(request).execute();
elapsed = System.currentTimeMillis() - start;
logger.debug("CallApi time = " + elapsed);
Related
I'm trying to create a GET request to retrieve commercial flights from latam. But I only get the answer through insomnia/postman...
I'm making the request through RestTemplate in Java, as shown below:
public class LatamRequest {
public void consumerAPILatam(){
RestTemplate template = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
//h.ttps://www.latamairlines.com/bff/air-offers/offers/search
UriComponents uri = UriComponentsBuilder.newInstance()
.scheme("https")
.host("www.latamairlines.com")
.path("bff/air-offers/offers/search")
.queryParam("sort","RECOMMENDED")
.queryParam("cabinType","Economy")
.queryParam("origin","GRU")
.queryParam("destination","BSB")
.queryParam("inFlightDate","null")
.queryParam("inFrom","null")
.queryParam("inOfferId","null")
.queryParam("outFlightDate","null")
.queryParam("outFrom","2022-11-15T15%3A00%3A00.000Z")
.queryParam("outOfferId","null")
.queryParam("adult","1")
.queryParam("child","0")
.queryParam("infant","0")
.queryParam("redemption","true")
.build();
headers.set("User-Agent", "test");
headers.set("Accept", "*/*");
headers.set("Content-Type", "application/json");
headers.set("X-latam-App-Session-Id", "84196897-1687-4d8c-8e63-083091ac204f");
headers.set("X-latam-Action-Name", "search-result.flightselection.offers-search");
headers.set("X-latam-Application-Name", "web-air-offers");
headers.set("X-latam-Client-Name", "web-air-offers");
headers.set("X-latam-Track-Id", "3a4ae189-e218-4606-bd9e-8b17efc93463");
headers.set("X-latam-Request-Id", "ff44ef24-e6d0-4cb0-984c-df1db18cee19");
headers.set("X-latam-Application-Country", "BR");
headers.set("X-latam-Application-Oc", "br");
headers.set("X-latam-Application-Lang", "pt");
HttpEntity<String> httpEntity = new HttpEntity<>(headers);
ResponseEntity<String> response = template.exchange(uri.toUriString(), HttpMethod.GET, httpEntity, String.class); //todo: No response, no error...
System.out.println(response);
}
}
I don't get any response or status after executing the above block. OBS: With the same parameters and headers I get status 200 in postman or insomnia.
I've tried several ways, but I can't get a response. Does anyone have any ideas for a more effective debug?
The reason that you don't get any response and no exception is because the server side gets your request and keeps holding it and doesn't respond. So you are still in a waiting mode. I ran your request from java code using different http client but used exact your params and I noticed that response never returns. I waited for over 10 minutes and I saw that the program was still running. So I modified the code and added connection timeout for 5 sec and read timeout for 30 seconds. When I ran it it I got read timeout exception after 30 seconds. So the code manages to connect to server side, but server side just doesn't respond. So you are in endless wait. So, I don't know why it works from postman. May be some headers values issues.
i'm trying to use the Asynchronous API of the java 11 HttpClient library to GET data from my server. But to be in line with the best practices, I want the client to throttle the request to the server to be a max of 100 requests every minute. How should this be accomplished in java 11 HttpClient library?
In python, there is the aiohttp library that allows you to specify the parameters for throttling the request.
Is there such a thing for java 11 HttpClient library as well?
HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_2)
.followRedirects(Redirect.SAME_PROTOCOL)
.proxy(ProxySelector.of(new InetSocketAddress("www-proxy.com", 8080)))
.authenticator(Authenticator.getDefault())
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://openjdk.java.net/"))
.timeout(Duration.ofMinutes(1))
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofFile(Paths.get("file.json")))
.build()
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(response -> { System.out.println(response.statusCode());
return response; } )
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
link: https://openjdk.org/groups/net/httpclient/intro.html
I want to create an Alarm when CPU memory/Hard Disk Memory is full. I am using spring-boot f/w along with Prometheus. I can view all metrics details on HTTP requests:- http://localhost:9090/actuator/prometheus. but IDK how can I fetch the data from Prometheus in my project to raise an alarm or to do any action.
your suggestion/links will be more valuable. Thank you.
You can scrap metrics from your actuator endpiont in the same way as Prometheus do it.
I use OkHttpClient for that.
Example of my client:
OkHttpClient client = new OkHttpClient.Builder()
.retryOnConnectionFailure(false)
.followRedirects(false)
.protocols(Collections.singletonList(Protocol.H2_PRIOR_KNOWLEDGE))
.build();
All settings are optional. But pay attention to the protocol - it should be the same as on your application's server.
After that you need to build url:
String url = "http://localhost:9090/actuator/prometheus?includedNames=<nameOfThePropertyThatYouNeed>";
You can include here more than 1 property:
String url = "http://localhost:9090/actuator/prometheus?includedNames=<propertyNameOne>,<propertyNameTwo>,<propertyNameThree>";
After that you make request:
Request request =new Request.Builder()
.url(url)
.get()
.build();
Response response = client.newCall(request).execute();
String responseBody = response.body().string();
Now you need to parse responseBody. Do it in the way as Prometheus does it and use classes of Prometheus:
InputStream inputStream = new ByteArrayInputStream(responseBody.getBytes())
CollectorPrometheusMetricsWalker walker = new CollectorPrometheusMetricsWalker();
PrometheusMetricsProcessor<MetricFamily> processor = new TextPrometheusMetricsProcessor(inputStream, walker);
processor.walk();
List<MetricFamily> metricList = walker.getAllMetricFamilies();
MetricFamily object stores all metrics with the same name but with different tags.
Use metricFamily.getMetrics() to get List<Metric>
Use metric.getValue() to get the value of metric.
You should use AlertManager that is part of Prometheus suit.
I am using java Apache HttpClient to request a resource (B) with a timeout of 10s. If timeout exceeds Broken pipe is seen at the other application server.
Because of which Nginx at application B is not caching the response. How to gracefully close the connection so that the other app server (B) does not encounter broken pipe exception.
If you're using new enough HttpClient can't you do something like this (I just found a snippet someone else had written ... but see below where I've added ###)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:8081/test/resource"))
.header("Accept", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("ping!"))
.build();
CompletableFuture<HttpResponse<String>> completableFuture =
client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
completableFuture
.completeOnTimeout(DEFAULT_RESPONSE, 1, TimeUnit.SECONDS) // ### ADD THIS the HttpClientRequest actually continues but the future has timed out so the user of the client progresses ??
.thenApplyAsync(HttpResponse::headers)
.thenAcceptAsync(System.out::println);
HttpResponse<String> response = completableFuture.join();
I am experiencing an issue with Okhttp + Node.js Formidable serverside big file upload.
Currently the upload works for < 100Mb files but fails for bigger files.
For bigger files, the onprogress event serverside is fired until 99% progress, regardless of the file size, then it stops, reports request abort, and the onfile event is not fired.
Already tried timeouts workarounds, even defined a custom SocketFactory to manually set the socket keepalive and sotimeout.
So, Im stuck here. Any help would be appreciated.
CustomSocketFactory MySocketFactory = new CustomSocketFactory();
OkHttpClient client = new OkHttpClient.Builder()
.socketFactory(MySocketFactory)
.readTimeout(largenumber, TimeUnit.SECONDS)
.writeTimeout(largenumber, TimeUnit.SECONDS)
.connectTimeout(largenumber, TimeUnit.SECONDS)
.build();
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("nombre_file", file_pais.getName())
.addFormDataPart("nombre_pais", pais.getName())
.addFormDataPart("file", file_pais.getName(),
RequestBody.create(MediaType.parse("application/octet-stream"),
new File(filepath)
.build();
Request request = new Request.Builder()
.url(server_url)
.post(requestBody)
.build();
Call call = client.newCall(request);
Response response = call.execute();
response.body().close();
Its way too easy using snoopy api: one line of code if you exclude identifiers definition :)
URI uri = ...;
Path fileToUpload = ...;
Snoopy.builder()
.config(SnoopyConfig.defaults())
.build()
.post(uri)
.followRedirects(true)
.failIfNotSuccessfulResponse(true)
.body(fileToUpload)
.consumeAsString();
https://bitbucket.org/abuwandi/snoopy
Tested on large files and it worked like a charm