Sunday, 5 August 2018

Spring Boot with Docker

Assuming demo is the project name and navigated into demo folder:

===========================================

Dockerfile (no extension)

FROM openjdk:8-jdk-alpine
VOLUME C:\\temp
ARG JAR_FILE=target/demo-0.0.1-SNAPSHOT.jar
EXPOSE 8080
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

===========================================

mvnw package ==> to build project

docker build -t demo .  ==> to create image
docker image ls
docker run -p 5000:8080 demo  ==> to run image

==========================================

Access instance using : http://localhost:5000/

==========================================

Remove Docker containers and images:
-----------------------------------------------

docker container ls
docker stop <container_id>   ==> To stop container
docker rm <container_id>     ==> to remove container

docker images -a
docker rmi <all image_ids>     ==> to remove image

Friday, 3 August 2018

Spring Boot Restful services - req/resp compression (zip)

In Spring Boot :

https://docs.spring.io/spring-boot/docs/1.4.3.RELEASE/reference/html/howto-embedded-servlet-containers.html#how-to-enable-http-response-compression

application.properties
server.compression.enabled=true
#if response if greater than or equal to 2048 bytes
server.compression.min-response-size=2048server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain


#if response if less than 2048 bytes, response looks like this:




==========================================================================
For additional info:
------------------------


To PUT data to the server compressed you must compress the request body and set the Content-Encoding: gzip header. The header itself must be uncompressed. It's documented in mod_deflate:
The mod_deflate module also provides a filter for decompressing a gzip compressed request body. In order to activate this feature you have to insert the DEFLATE filter into the input filter chain using SetInputFilter or AddInputFilter.
...
Now if a request contains a Content-Encoding: gzip header, the body will be automatically decompressed. Few browsers have the ability to gzip request bodies. However, some special applications actually do support request compression, for instance some WebDAV clients.
And an article describing it is here:
So how do you do it? Here is a blurb, again from the mod_deflate source code: only work on main request/no subrequests. This means that the whole body of the request must be gzip compressed if we chose to use this, it is not possible to compress only the part containing the file for example in a multipart request.
Separately, a browser can request server response content to be compressed by setting Accept-Encoding header as per here:
GET /index.html HTTP/1.1
Host: www.http-compression.com
Accept-Encoding: gzip
User-Agent: Firefox/1.0
This will return compressed data to the browser.

Wednesday, 1 August 2018

CircuitBreaker/Hystrix - Microservices - Spring Boot

Hystrix

If you have, let’s say 3 services, A calls → B, and B calls → C service. What if, a failure happened at B? The error will cascade down to service C, right?.
A -> B (failure) -> C
Another example, lets say a service A calls a remote service R, and for some reason the remote service is down. How can we handle such a situation?
What we would like to do is stop failures from cascading down, and provide a way to self-heal, which improves the system’s overall resiliency.
Hystrix is the implementation of Circuit Breaker pattern, which gives a control over latency and failure between distributed services.
The main idea is to stop cascading failures by failing fast and recover as soon as possible — Important aspects of fault-tolerant systems that self-heal.
So, we’ll add Hystrix to gallery service, and we’ll simulate a failure at image service. In the pom.xml file
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
In the spring boot main class
// ...@EnableCircuitBreaker      // Enable circuit breakers
public class SpringEurekaGalleryApp {
  public static void main(String[] args) {
    SpringApplication.run(SpringEurekaGalleryApp.class, args);
  }
}
Spring looks for any method annotated with the @HystrixCommandannotation, and wraps that method so that Hystrix can monitor it.
Hystrix watches for failures in that method, and if failures reached a threshold (limit), Hystrix opens the circuit so that subsequent calls will automatically fail. Therefore, and while the circuit is open, Hystrix redirects calls to the fallback method.
So, In the controller class, update getGallery(), add annotation and fallback method.

package com.eureka.gallery.controllers;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.env.Environment;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;
import com.eureka.gallery.entities.Gallery;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@RestController
@RequestMapping("/")public class HomeController {
    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "fallback")
    @RequestMapping("/{id}")
    public Gallery getGallery(@PathVariable final int id) {
        // create gallery object        Gallery gallery = new Gallery();
        gallery.setId(id);

        // get list of available images         @SuppressWarnings("unchecked")    // we'll throw an exception from image service to simulate a failure                List<Object> images = restTemplate.getForObject("http://image-service/images/", List.class);
        gallery.setImages(images);

        return gallery;
    }

    // a fallback method to be called if failure happened    public Gallery fallback(int galleryId, Throwable hystrixCommand) {
        return new Gallery(galleryId);
    }
}
In the controller class of image service, throw an exception in getImages()
throw new Exception("Images can't be fetched");
Now, go to the browser, and hit localhost:8762/gallery/1. You should get an empty gallery object (no images).
{
    "id": 1,
    "images": null
}