One of the core features of Hystrix is what is called resource isolation. The core problem to solve is to isolate calls to multiple dependent services into their own resource pools. Avoid making calls to a dependent service because all thread resources of the service are expended on that service’s interface call due to a delay or failure of the interface call. Once a service is said to be running out of thread resources, it can cause the service to crash, or even spread.

Hystrix implements resource isolation using two main technologies:

  • The thread pool
  • A semaphore

By default, Hystrix uses thread pool mode.

This article will discuss the semaphore mechanism for resource isolation and the differences and application scenarios between the two technologies.

Semaphore mechanism

For example, if the semaphore size of service A is 10, then only 10 Tomcat threads are allowed to access service A at the same time, and all other requests are rejected, thus achieving resource isolation and traffic limiting protection.

Thread pools and semaphores

Thread pool isolation is not about controlling threads in web containers like Tomcat. In a more rigorous sense, Hystrix’s thread pool isolation technology controls the execution of tomcat threads. When the Hystrix thread pool is full, it ensures that Tomcat threads are not hung due to delays or failures in service-dependent interface calls, and other Tomcat threads are not stuck and can quickly return to support other things.

Thread pool isolation, which uses Hystrix’s own threads to execute calls; Semaphore isolation, on the other hand, allows the Tomcat thread to invoke the dependent service directly. Semaphore isolation is just a checkpoint that allows as many Tomcat threads to pass through it and execute.

Applicable scenarios:

  • Thread pool technology is suitable for most scenarios, such as when we call and access network requests that depend on services, and need to control timeout calls (catch timeout exceptions).
  • Semaphore technology, suitable to say that your visit is not external dependence, but the inside some of the more complex business logic, and the system of internal code, actually does not involve any network request, then as long as do ordinary current-limiting semaphore is ok, because they don’t need to capture the timeout similar problems.

Semaphore simple Demo

What is a good scenario for semaphores in a business context?

A caching service, for example, might store a very small amount of data in its own pure memory that is accessed very frequently.

Here’s an example. Generally, after obtaining the commodity data, we need to obtain the geographical location, province, city and seller of the commodity, which may be obtained in our own pure memory, such as a Map. For this type of direct access to local memory logic, simple isolation with semaphores is a good idea.

The advantages are that there is no need to manage the thread pool yourself, no care timeout timeout, and no context switch for threads. Semaphore isolation, relatively higher performance.

So if this is a local cache, we can get cityName by cityId.

public class LocationCache { 
  private static Map<Long, String> cityMap = new HashMap<>(); static { 
    cityMap.put(1L."Beijing"); 
  }
	/** * Get cityName * from cityId@paramCityId cityId *@returnCity name * / 
	public static String getCityName(Long cityId) { 
    returncityMap.get(cityId); }}Copy the code

Write a GetCityNameCommand with policy set to semaphore. Get the local cache in the run() method. The goal is to resource isolate the code that gets the local cache.

public class GetCityNameCommand extends HystrixCommand<String> { 
  private Long cityId; public GetCityNameCommand(Long cityId) { 
    // Set the semaphore isolation policy
    super(Setter.withGroupKey(
      	HystrixCommandGroupKey.Factory.asKey("GetCityNameGroup")) 
          .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() 
          	.withExecutionIsolationStrategy(HystrixCommandProperties
            	.Execut ionIsolationStrategy.SEMAPHORE))); 
    this.cityId = cityId; 
  }
	@Override 
	protected String run(a) {
    // The code that needs semaphore isolation
    returnLocationCache.getCityName(cityId); }}Copy the code

At the interface level, the code that retrieves the local cityName cache will isolate the semaphore resource by creating GetCityNameCommand, passing in the cityId, and executing the execute() method.

@RequestMapping("/getProductInfo") 
@ResponseBody
public String getProductInfo(Long productId) { 
  HystrixCommand<ProductInfo> getProductInfoCommand = new GetProductInfoCommand(productId);
  // Run the command to obtain the latest commodity data
  ProductInfo productInfo = getProductInfoCommand.execute(); 
  Long cityId = productInfo.getCityId(); 
  GetCityNameCommand getCityNameCommand = new GetCityNameCommand(cityId); 
  // The code that gets local memory (cityName) is resource isolated by the semaphore
  String cityName = getCityNameCommand.execute(); 
  productInfo.setCityName(cityName); 
  System.out.println(productInfo); 
  return "success"; 
}
Copy the code