Microsoft Service Framework--Spring Cloud

SpringCloud

The official website explains that spring Cloud provides developers with tools to quickly build some common patterns in distributed systems (such as configuration management, service discovery, circuit breakers, intelligent routing, micro-agent, control bus, one-time token, global lock, leadership election, distributed session, cluster state). Coordination of distributed systems leads to boiler board patterns, and developers using Spring Cloud can quickly build services and applications that implement these patterns. They work well in any distributed environment, including developers'own laptops, bare data centers, and hosting platforms such as cloud computing. First, Spring Cloud was developed based on Spring Boot.

I. Service Registration in Discovery (Eureka)

Spring Cloud Netflix has its own component Eureka as a registry to achieve service coordination, load balancing, fault tolerance, routing and so on.

Create the Eureka Server project to open the registry:

 <parent> 
  <groupId>org.springframework.boot</groupId> 
  <artifactId>spring-boot-starter-parent</artifactId> 
  <version>1.5.2.RELEASE</version> 
  <relativePath /> <!-- lookup parent from repository --> 
 </parent> 
 <properties> 
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 
  <java.version>1.8</java.version> 
 </properties> 
 
 <dependencies> 
  <!--eureka server --> 
  <dependency> 
   <groupId>org.springframework.cloud</groupId> 
   <artifactId>spring-cloud-starter-eureka-server</artifactId> 
  </dependency> 
  <!-- spring boot test --> 
  <dependency> 
   <groupId>org.springframework.boot</groupId> 
   <artifactId>spring-boot-starter-test</artifactId> 
   <scope>test</scope> 
  </dependency> 
 </dependencies> 
<dependencyManagement> 
  <dependencies> 
   <dependency> 
    <groupId>org.springframework.cloud</groupId> 
    <artifactId>spring-cloud-dependencies</artifactId> 
    <version>Dalston.RC1</version> 
    <type>pom</type> 
    <scope>import</scope> 
   </dependency> 
  </dependencies> 
 </dependencyManagement> 
 

Setup configuration file: application.yml

server:
   port: 8888
eureka:
   instance:
     hostname: localhost   
   client:
     registerWithEureka: false
     fetchRegistry: false
     serviceUrl:
       defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 

Start Eureka:

@SpringBootApplication 
@EnableEurekaServer 
public class App { 
 public static void main(String[] args) { 
  SpringApplication.run(App.class, args); 
 } 
}

Create a service provider: member-service

Configuration file: application.yml registers the service provider with the registry Eureka

eureka: 
  client: 
    serviceUrl: 
      defaultZone: http://localhost:8888/eureka/ 
server: 
  port: 8762 
spring: 
  application:
     name: member-service

Service interface:

@RestController 
public class MemberController { 
 
 @RequestMapping("/getUserList") 
 public List<String> getUserList() { 
  List<String> listUser = new ArrayList<String>(); 
  listUser.add("zhangsan"); 
  listUser.add("lisi"); 
  listUser.add("wangwu"); 
  return listUser; 
 } 
 
} 
 

Open Services:

@SpringBootApplication 
@EnableEurekaClient 
public class AppMember { 
 
 public static void main(String[] args) { 
  SpringApplication.run(AppMember.class, args); 
 } 
 
} 

3. Service consumer order-service

Configuration file: application.yml

eureka: 
  client: 
    serviceUrl: 
      defaultZone: http://localhost:8888/eureka/ 
server: 
  port: 8764 
spring: 
  application:
     name: order-service

Write the service and call the service producer:

@Service 
public class MemberService { 
 @Autowired 
 RestTemplate restTemplate; 
 
 public List<String> getOrderByUserList() { 
  return restTemplate.getForObject("http://service-member/getUserList", List.class); 
 }  
} 
 

Start the project:

@EnableEurekaClient 
@SpringBootApplication 
public class AppOrder { 
 
 public static void main(String[] args) { 
  SpringApplication.run(AppOrder.class, args); 
 } 
 
//Configure Bean properties, inject a Bean into IOC, and indicate load balancing by @LoadBalance
 @Bean 
 @LoadBalanced 
 RestTemplate restTemplate() { 
  return new RestTemplate(); 
 } 
 
} 
 
 

IV. Load Balancing of Service Governance - ribbon (Fegin Default Integration)

Ribbon, like Nginx reverse proxy, routes requests to specified services through load balancing algorithms. Use restTemplate to enable load balancing through the @LoadBalanced annotation

Fegin implementations only need to annotate @FeginCilent("service name") on the class of the exposed interface. Fegin integrates Rebbon by default, similar to Dubbo's exposed service, but Fegin is a declarative http client and Dubbo is based on private binary protocol.

Routing Gateway-Zuul

Zuul's main functions are routing forwarding and filtering. Routing functions are part of micro services, such as / api/user forwarding to user services and / api/shop forwarding to shop services. Zuul implements load balancing by default and Ribbon, similar to nginx forwarding.

Configuration file configuration:

eureka: 
  client: 
    serviceUrl: 
      defaultZone: http://localhost:8888/eureka/ 
server: 
  port: 8769 
spring: 
  application: 
    name: service-zuul 
zuul: 
  routes: 
    api-a: 
      path: /api-member/** 
      service-id: service-member 
    api-b: 
      path: /api-order/**
       service-id: service-order 

Send request http://127.0.0.1:8769/api-member/getMemberAll forwarded to http://127.0.0.1:8762/getMemberAll open gateway@EnableZuulProxy

Service filtering:

@Component 
public class MyFilter extends ZuulFilter { 
 
 private static Logger log = LoggerFactory.getLogger(MyFilter.class); 
 
 @Override 
 public String filterType() { 
  return "pre";  
 } 
 
 @Override 
 public int filterOrder() { 
  return 0; 
 } 
 
 public boolean shouldFilter() { 
  return true; 
 } 
 
 public Object run() { 
  RequestContext ctx = RequestContext.getCurrentContext(); 
  HttpServletRequest request = ctx.getRequest(); 
  log.info(String.format("%s >>> %s", request.getMethod(), 
  request.getRequestURL().toString())); 
  Object accessToken = request.getParameter("token"); 
  if (accessToken != null) { 
   return null; 
  } 
  log.warn("token is empty"); 
  ctx.setSendZuulResponse(false); 
  ctx.setResponseStatusCode(401); 
  try { 
   ctx.getResponse().getWriter().write("token is empty"); 
  } catch (Exception e) { 
  } 
  return null; 
 
 } 
} 

Sixth, Service Governance, Solution to Server Avalanche Response Strategy-Circuit Breaker (Hystrix)

In the micro-service architecture, we divide business into services one by one, and services and services can call each other (RPC). In order to ensure its high availability, a single service must be deployed in a cluster. Because of network reasons or its own reasons, services can not guarantee 100% availability of services. If a single service has problems, the call of this service will lead to network delay. At this time, if there is a large number of network influx, it will form a task accumulation, resulting in service paralysis, and even lead to service "avalanche". To solve this problem, circuit breaker model appears.  
Hystrix is a class library that helps solve the problem of timeout and fault tolerance in distributed system interaction. It also has the ability to protect the system.
In distributed systems, the unavailability of one basic service often results in the unavailability of the whole system. This phenomenon is called service avalanche effect. In order to cope with service avalanche, a common method is manual service degradation. The emergence of Hystrix provides us with another option.

1. Fuse design:

(1) Fuse request judgment mechanism algorithm: using unlocked loop queue count, each fuse maintains 10 buckets by default, one bucket per second. Each blucket records the status of success, failure, timeout and rejection of requests. The default error exceeds 50% and more than 20 requests are intercepted within 10 seconds.  
(2) Fuse recovery: For fused requests, partial requests are allowed to pass every five seconds, and if all requests are healthy (RT < 250ms), the request for health recovery is allowed.   
(3) Fuse alarm: Log the request for fuse, and alarm if the exception request exceeds certain settings.

2. Isolation design:

(1) Thread pool isolation mode: use a thread pool to store current requests, thread pool to process requests, set task return processing time-out, accumulate requests into the thread pool queue. This method needs to apply for thread pool for each dependent service, which consumes a certain amount of resources. The advantage of this method is that it can deal with sudden traffic (when the peak of traffic arrives, the data can be stored in the thread pool team and processed slowly).
(2) semaphore isolation mode: use an atomic counter (or semaphore) to record how many threads are currently running, request to determine the value of the counter first, if the maximum number of threads exceeds the set, discard the new request to change the type, if not more than the count operation request to counter + 1, request to return Counter-1. This method is a strict thread control and immediate return mode, unable to cope with sudden traffic (when the flow peak arrives, the number of threads processed exceeds, other requests will return directly, do not continue to request dependent services)

3. Timeout design:

Waiting time-out: Set up the task queuing time when the task enters the queue, and judge whether the queue head's task enters the queue time is longer than the time-out time, and discard the task if it exceeds the time-out time.  
Running timeout: You can directly use the get method provided by the thread pool

Service degradation:

When the service is unavailable, there will be no abnormality in the circuit breaker using rest mode. The degrading method is to call back the original service when it is unavailable. The front desk returns to "too many connections, please try later!"

//Rest Request Interface Modification 
@HystrixCommand(fallbackMethod = "orderError") 
public List<String> getOrderUserAll() { 
return restTemplate.getForObject("http://service-member/getMemberAll", List.class); 
} 
 
public List<String> orderError() { 
 List<String> listUser = new ArrayList<String>(); 
 listUser.add("not orderUser list"); 
 return listUser; 
}

Then start the project. Start the class as before, just add the @EnableHystrix annotation on the original class to start the circuit breaker, where @HystrixCommand indicates the callback method for the service to be wrong.

(2) Fegin implements circuit breaker, which balances load while proxying service, sets callback function, and calls callback function when problems arise.

@FeignClient(value="service-member",fallback=MemberFeignService.class) 
public interface MemberFeign {  

    @RequestMapping("/getMemberAll")  
    public List<String> getOrderByUserList(); 
} 

   
 @Component 
 public class MemberFeignService implements MemberFeign { 
 
 public List<String> getOrderByUserList() { 
  List<String> listUser = new ArrayList<String>(); 
  listUser.add("not orderUser list"); 
  return listUser; 
 } 
} 

Modify the configuration file and add it to it.

fegin: 
    hystrix: 
        enable: true

The basic content of Spring Cloud is finished. Please refer to the official documents of Spring Cloud for more information.

Keywords: Spring network Java Nginx

Added by kneifelspy on Mon, 26 Aug 2019 12:44:55 +0300