Microservices

Eureka and Feign

Eureka

Eureka is a REST (Representational State Transfer) based service used for locating services for the purpose of load balancing and failover of middle-tier servers. We have eureka client and server. The server holds the information regarding the service instances, while the client interacts with the server and act as a round robin load balancer. Basically, eureka takes care of the A(availability) in the CAP theorem. If you remember load balancers in the old days were working with fixed ip addresses, but in a microservice environment there are moving parts and they simply are not enough. Today needs are to register/de-register services on the fly.

Basically you need a discovery service that acts as a server

@EnableEurekaServer
@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

and some clients with @EnableEurekaClient.

@Configuration
@ComponentScan("com.so")
@EnableEurekaClient
@Import({BidConfiguration.class, EventuateDriverConfiguration.class})
public class BidWebConfiguration {

}

If everything went according to plan, we should see all the clients registered with Eureka. One huge advantage is that it resolves the session affinity. No stickiness and no need for cache for storing session data. Eureka will handle everything. The end result will show like this:

Screen Shot 2017-08-31 at 23.45.15

Feign

Feign is a declarative HTTP client developed by Netflix. It works hand in hand with Eureka. Since Eureka can register/de-register services on the fly, Feign takes care of the interaction with these. In a normal situation we have multiple instances for one service in case something goes wrong or for performance reasons. This means we need some kind of interface for each service.

@FeignClient("BID-COMMAND")
public interface BidCommandFeignClient {

   @RequestMapping(value = "/bids", method = RequestMethod.POST)
   ResponseEntity<String> createBid(@RequestBody BidRequest bid);

}

This exposes all the interaction with this service, and each instance must respect this contract.

@RestController
public class BidController implements BidCommandFeignClient {

	private BidService bidService;

	@Autowired
	public BidController(BidService bidService) {
		this.bidService = bidService;
	}

	public ResponseEntity<String> createBid(@RequestBody BidRequest bid) {
	       CompletableFuture<ResponseEntity> future = bidService.addBid(bid.getItemCode(), bid.getAmount())
                       .thenApply(b -> new ResponseEntity(b.getEntityId(), HttpStatus.OK));
               return future.get();
	}
}

Now these clients must be discovered and enabled, and this is the role of the api-gateway.

@Configuration
@EnableFeignClients(basePackages = { "com.so.feign" })
@ComponentScan("com.so")
public class FeignConfiguration {
}

The api gateway is a facade that interacts with all the feign clients. It only knows about the Feign client interfaces, it has no dependency to the implementations.

@RestController
public class ApiController {
	
	@Autowired
	private BidCommandFeignClient bidCommandFeignClient;

	@RequestMapping(value = "/bids", method = RequestMethod.POST)
	private ResponseEntity<String> createBid(@RequestBody BidRequest bid) {
		return bidCommandFeignClient.createBid(bid);
	}
}

The gateway must be a @EurekaClient in order to be able to fetch the registry.

Screen Shot 2017-09-01 at 00.13.10

Now let’s load two instances of a service, and see how our application is impacted by one failing.

Screen Shot 2017-09-01 at 00.17.16

As you can see we have 2 instances of ITEM-VIEW service. If we kill the original instance, the second one will take over without any impact to the user experience. You can test this using the postman project provided.

Screen Shot 2017-09-01 at 00.20.51

Eureka will evict the failing instance after a timeout that we can specify.

Some important things to keep in mind:

  • make sure your docker instance has enough memory (or use mem_limit in docker-compose 2). More details here.

  • you could receive timeouts on first call, and subsequent calls to work without any issues

  • currently Feign has no CompletableFuture support, or at least I cannot get it to work with it (but this is beyond the scope of this post)

  • Feign requires generic type for ResponseEntity<T> and a value for @PathVariable(value=’x’)

  • Feign uses Ribbon under the hood for load balancing

 SOURCE_CODE

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s