Spring cloud series, spring cloud overview and the use of microservice technology stack

Keywords: Spring Cloud Microservices

1. Introduction to spring cloud

SpringCloud Is an ordered collection of a series of frameworks. Taking advantage of the development convenience of SpringBoot, it cleverly simplifies the development of basic settings of distributed systems, such as service discovery and registration, configuration center, message bus, load balancing, circuit breaker, data monitoring, etc., which can be started and deployed with one click with the development style of SpringBoot. Spring cloud does not repeatedly manufacture wheels. It just combines the service frameworks developed by various companies that are relatively mature and can stand the postgraduate entrance examination, re encapsulates them through the SpringBoot style, shields the complex configuration and implementation principles, and finally flows a set of simple, easy to understand, easy to deploy and easy to maintain distributed system development tools to developers.

1.1. Five core components in spring cloud

The essence of Spring Cloud is to add a bunch of microservice related specifications on the basis of SpringBoot and enhance the function of application context. Since Spring Cloud is a specification, it needs to be implemented. At present, Spring Cloud specifications have been implemented by Spring officials, Spring Cloud Netflix, Spring Cloud Alibaba, etc. Through componentization, Spring Cloud integrates these implementations to form a bucket like microservice technology stack.

SpringCloud Netflix components

Component nameeffect
EurekaService registry
RibbonClient load balancing
FeignDeclarative service side call (based on the Ribbon, change the call method from RestTemplate to service interface call)
HystrixClient fault tolerant alarm protection (fuse degradation service)
ZuulAPI service gateway

Spring Cloud Alibaba component

Component nameeffect
NacosService registry
SentinelClient fault tolerance protection

Spring Cloud native and other components

assemblyeffect
Consul (Eureka replacement)Service registry
ConfigDistributed configuration center
Gateway (Zuul replacement)API service gateway
SleuthDistributed Link Tracking

1.2. Architecture of spring cloud


As can be seen from the above figure, the cooperation of various components of spring cloud supports a complete set of microservice architecture.

  • Registration Center: it is responsible for the registration and discovery of services and connects services well
  • Circuit breaker: it is responsible for monitoring the call between services. In case of continuous failure for many times, fuse degradation protection will be carried out
  • API gateway: responsible for forwarding all external requests and services
  • Configuration center: provides a unified configuration information management service, which can notify each service to obtain the latest configuration information in real time
  • Link Tracking Technology: all data can be recorded for subsequent analysis
  • Each component also provides a fully functional dashboard monitoring platform, which can easily monitor the operation status of each component

1.3. Microservices and microservice architecture

Microservices:

The emphasis is on the size of the service. It focuses on a certain point. It is a service application that specifically solves a problem / provides floor-to-floor corresponding services. In a narrow sense, it can be regarded as a microservice project or Moudle module in the IDEA. The IDEA tool uses independent Moudel developed by Maven. Specifically, it uses a small module developed by SpringBoot. Professional things are handed over to professional modules. Each module does one thing. It emphasizes that each individual completes a specific task or function.

Microservice architecture:

A new architecture form was proposed by Martin Fowler in 2014.
Microservice architecture is an architecture model. It advocates dividing a single application into a group of small services. Services coordinate and cooperate with each other to provide final value for users. Each service runs in its own process. Services and services cooperate with each other by using lightweight communication mechanism (such as HTTP protocol). Each service is built around specific business, And can be independently deployed to the production environment. In addition, a unified and centralized service management mechanism should be avoided as far as possible. For a specific service, appropriate languages and tools (such as maven) should be selected for unified construction according to the business context.

1.4 overview of microservice technology stack

Microservice Technology Entrytechnical support
Service developmentSpring,SpringBoot,SpringMVC
Service configuration and managementArchaius of Netflix, Diamond of Ali, etc
Service registration and discoveryEureka,Consul,Zookeeper
Service callRset,RPC,gRPC
Service fuseHystrix, Envoy, etc
load balancing Ribbon, Nginx, etc
Service interface call (simplified tool for client to call service)Feign et al
Message queueRabbitMQ, ActiveMQ, Kafka, etc
Service configuration center managementSpringCLoudConfig, Chef, etc
Service routing (API gateway)Zuul et al
Service monitoringZabbix, Nagios, Metrics, specifier, etc
Full link trackingZipkin, Brave, Dapper, etc
Data flow operation development packageSpring cloud stream (encapsulating sending and receiving messages with Redis, Rabbit, Kafka, etc.)
Time message stackSpringCloud Bus
Service deploymentDocker, OpenStack, Kuberneters, etc

1.5 why did you choose spring cloud as the microservice architecture?

Type selection I basis

  • Overall solution and framework maturity
  • Community heat
  • Maintainability
  • learning curve

What are the current microservice architectures used by major IT companies?

  • Ali: dubbo+HFS
  • JD: JFS
  • Sina: Motan
  • Dangdang: DubboX

1.6 relationship between SpringCloud and SpringBoot

  • SpringBoot focuses on developing individual microservices quickly and easily
  • SpringCloud is a microservice coordination and management framework that focuses on the overall situation. It integrates and manages individual microservices developed by SpringBoot, and provides integrated services between microservices: configuration management, service discovery, circuit breaker, routing, agent, event stack, decision-making campaign, distributed session and so on
  • SpringBoot can be used independently of SpringCloud to develop projects, but SpringCloud is inseparable from SpringBoot and belongs to dependency

1.7 selection of Dubbo and SpringCloud technologies

1. Distributed + service governance Dubbo

  • The current mature Internet architecture, application service splitting + message middleware

2. Comparison between Dubbo and spring cloud
Take a look at community activity: Dubbo and SpringCloud

DubboSpringCloud
Service registryZookeeperSpring Cloud Netflix Eureka
Service invocation modeRPCREST API
Service monitoringDubbo-monitorSpringBoot Admin
Circuit breakerimperfectSpringCloud Netflix Hystrix
Service gatewaynothingSpring Cloud Netflix Zuul
Distributed configurationnothingSpring Cloud Config
Service trackingnothingSpring Cloud Sleuth
Message stacknothingSpring Cloud Bus
data streamnothingSpring Cloud Stream
Batch tasknothingSpring Cloud Task

The biggest difference between the two lies in the communication mode:
Spring cloud abandons Dubbo's RPC communication and adopts the REST API based on lightweight HTTP protocol.
Strictly speaking, these two methods have their own advantages and disadvantages. RPC is superior to REST in performance, but REST is more flexible than RPC in flexibility. Service providers and callers only need a consistent contract, and there is no strong dependence at the code level. This advantage is more appropriate in the current microservice environment that emphasizes rapid evolution.

The two solve different problem domains: Dubbo is positioned as an RPC framework, while the goal of spring cloud is a one-stop solution under the microservice architecture.

1.8 what can spring cloud do?

  • Distributed/Versioned configuration
  • Service registration and discovery
  • Routing
  • Service to service calls service to service calls
  • Load balancing policy
  • Circuit Breakers
  • Distributed messaging

1.9. Download from SpringCloud official website

SpringCloud official website

Spring cloud does not name the version number by numerical number, but uses the name of London underground station, and corresponds to the version time order according to the order of alphabet:

  • The earliest real version: Angel,
  • The second Realse version: Brixton,
  • Then Camden, Dalston, Edgware,
  • At present, the latest is the general stable version of Hoxton SR4 CURRENT GA.

1.10. Spring cloud version selection

Large Version Description

SpringBootSpringCloudrelationship
1.2XAngel versionCompatible with SpringBoot1.2X
1.3XBrixton Version (Brixton)Compatible with springboot 1.3x and springboot 1.4x
1.4XCamden Version (Camden)Compatible with SpringBoot1.4X and SpringBoot1.5X
1.5XDalston Version (dorston)Compatible with SpringBoot1.5X, incompatible with SpringBoot2.0X
1.5XEdgware Version (edgwell)Compatible with SpringBoot1.5X, incompatible with SpringBoot2.0X
2.0XFinchley Version (Finchley)Incompatible with SpringBoot1.5X, compatible with SpringBoot2.0X
2.1XGreenwich Version (Greenwich)

Actual development version relationship

spring-boot-starter-parentspring-cloud-dependencies
Version numberRelease dateVersion numberRelease date
1.5.2.RELEASE2017-03Dalston.RC12017-x
1.5.9.RELEASE2017-11Edgware.RELEASE2017-11
1.5.16.RELEASE2018-04Edgware.SR52018-10
1.5.20.RELEASE2018-09Edgware.SR52018-10
2.0.2.RELEASE2018-05Fomchiey.BULD-SNAPSHOT2018-x
2.0.6.RELEASE2018-10Fomchiey-SR22018-10
2.1.4.RELEASE2019-04Greenwich.SR12019-03

2. Case building and analysis based on Eureka registry

Spring cloud series (I), Eureka foundation of Service Registry [detailed tutorial]

3. Eureka's alternative Consul

Closed source effect of Eureka

Announce Eureka 2.x closed source on Eureka's GitHub. This means that if developers continue to use the code base and artifacts published as part of the repo of existing work on the 2.x branch, they will be at their own risk.

Eureka's alternative is as follows:

  • ZooKeeper It is a distributed and open source distributed application coordination service. It is an open source implementation of Chubby of Google and an important component of Hadoop and Hbase. It is a software that provides consistency services for distributed applications. Its functions include configuration maintenance, domain name service, distributed synchronization, group service, etc.
  • Consul It is a popular service discovery tool in recent years. It is used in work. Let's have a brief understanding. Three main application scenarios of consumer: service discovery, service isolation, and service configuration.
  • Nacos It is a new open source project launched by Alibaba. It is a dynamic service discovery, configuration management and service management platform that is easier to build cloud native applications. Nacos is dedicated to helping you discover, configure, and manage microservices. Nacos provides a set of easy-to-use feature sets to help you quickly realize dynamic service discovery, service configuration, service metadata and traffic management. Nacos helps you build, deliver, and manage microservice platforms more quickly and easily. Nacos is a service infrastructure for building "service" centered modern application architecture (such as micro service paradigm and cloud native paradigm).

3.1. Consul overview


Consul is an open source tool launched by HashiCorp, which is used to realize service discovery and configuration of distributed systems. Consul's scheme is more "one-stop" than other distributed service registration and discovery schemes,

  • Built in service registration and discovery framework
  • Implementation of distributed consistency protocol
  • health examination
  • Key/Value storage
  • Multi data center solution

There is no need to rely on other tools (such as ZooKeeper) and it is easy to use. Consul is written in Go language, so it has natural portability (supports Linux, windows and Mac OS X); The installation package contains only one executable file, which is convenient for deployment and can be seamlessly matched with lightweight containers such as Docker.

3.2 advantages of consult

  • Using the Raft algorithm to ensure consistency is more direct than the complex Paxoa algorithm. In comparison, Zookeeper uses Paxos and etcd uses Raft
  • Support multiple data centers, and different ports are used for monitoring the services of internal and external networks. Multi data center cluster can avoid single point of failure of single data center, and its deployment needs to consider network delay, fragmentation, etc. zookeeper and etcd do not provide support for multi data center functions
  • Health detection is supported, but etcd does not provide this function
  • Supports HTTP and DNS protocol interfaces. The inheritance of zookeeper is complex. etcd only supports HTTP protocol
  • The official web management interface is provided, but etcd does not have this function
  • Through comprehensive comparison, Consul, as a service registration and configuration management, is worthy of attention and research

Consul features:

  • Service discovery
  • Multi data center
  • key/value storage
  • Health testing

3.3 differences between Consul and Eureka

Consul has strong consistency (CP):

  • The service registration is slightly slower than Eureka, because consol's Raft protocol requires that more than half of the nodes write successfully before the registration is considered successful
  • After the Leader hangs up, the whole Consul is unavailable during the re-election, ensuring strong consistency, but sacrificing availability

Eureka guarantees high availability and final consistency (AP):

  • Service registration is relatively fast, because it is not necessary to wait for the registration information to be replicated to other nodes, and it is not guaranteed whether the registration information is replicated successfully
  • When the data is inconsistent, although the registration information on A and B are not exactly the same, each Eureka node can still provide services normally. When querying the service information, if request A cannot find it, but request B can find it (but the content is not necessarily consistent), this ensures high availability but sacrifices consistency

Development language and usage:

  • Eureka is a servlet program that runs in a servlet container
  • Consul is written by go and can be installed and started

3.4. Download and installation of consult

visit Download from Consul official website The latest version of consul. Consul needs to be installed separately. Here is consul1.5x. Select different installation packages according to different system types. It can also be seen from the figure below that consul supports all mainstream systems.

To install the Consul service in a Linux virtual machine:

## Download the latest version of Consul service from the official website
wget https://releases.hashicorp.com/consul/1.5.3/consul_1.5.3_linux_amd64.zip
##Unzip the file using the unzip command
unzip consul_1.5.3_linux_amd64.zip
##Copy the unzipped consumer executable command to the / usr/local/bin directory
cp consul /usr/local/bin
##Test it
consul

Start Consul service:

##Developer mode quick start is enabled, - client specifies the ip address that the client can access
[root@node01 ~]# consul agent -dev -client=0.0.0.0
==> Starting Consul agent...
     Version: 'v1.5.3'
     Node ID: '49ed9aa0-380b-3772-a0b6-b0c6ad561dc5'
    Node name: 'node01'
   Datacenter: 'dc1' (Segment: '<all>')
     Server: true (Bootstrap: false)
   Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
  Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
     Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false,
Auto-Encrypt-TLS: false

Access after successful startup: http://IP Address: 8500, you can see the Consul management interface:

For the time being, we will start the Consul service with the version under windows: download the zip of the windows version from the official website and unzip it without installation:

Enter the start Consu command:

#-client=0.0.0.0 is to open all ip access
consul agent -dev -client=0.0.0.0

After startup, access the address bar: localhost:8500

3.5 Consul's K/V storage

You can refer to the KV storage provided by Consul API Complete Consul based data storage

meaningRequest pathRequest mode
View keyv1/kv/:keyGET
Save or updatev1/kv/:keyPUT
deletev1/kv/:keyDELETE
  • The key value can contain /, which can be regarded as different directory structures.
  • The value of value has passed base64_encode encryption, Base64 after obtaining the data_ Decode decryption can get the original value. Data cannot be greater than 512Kb
  • kv storage systems in different data centers are independent, using dc =? Parameter assignment.

3.6. Consul based service registration case

The project configuration is still consistent with Eureka (for reference):
Spring cloud series (I), Eureka foundation of Service Registry [detailed tutorial]

ebuy-consul-parent(Parent module)
---ebuy-consul-product(Commodity (micro service)
---ebuy-consul-order(Order (micro service)

Modify the pom file of the goods and order micro service module:

	<!--SpringCloud Provided based on Consul Service discovery for-->
	<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    </dependency>
	<!--actuator For heartbeat check-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

Configure service registration
application.yml of Ebuy consumer product

server:
  port: 9011 #Port number

spring:
  application:
    name: ebuy-product #Commodity module service name
  datasource:
    username: root #Database user name
    password: root #Database password
    driver-class-name: com.mysql.jdbc.Driver #mysql load driver
    url: jdbc:mysql://localhost:3306/ebuy?useUnicode=true&characterEncoding=utf8
  cloud:
    consul:
      host: 127.0.0.1 #Specify the consumer service address
      port: 8500 #Specify the consumer service port number
      discovery:
        register: true #Register
        instance-id: ${spring.application.name}-1 #Specify the instance id name
        server-name: ${spring.application.name} #Service instance name
        port: ${server.port} #Service instance port number
        health-check-path: /actuator/health  #Health detection path
        health-check-interval: 15s #Specify the health test interval
        prefer-ip-address: true #Enable ip address registration
        ip-address: ${spring.cloud.client.ip-address} #Instance request ip

#mybatis related configuration
mybatis:
  type-aliases-package: com.ebuy.product.pojo  #mybatis simplifies pojo entity class aliases
  mapper-locations: com/ebuy/product/mapper/*.xml #mapper mapping file path

#Print log
logging:
  level:
    com.ebuy: DEBUG #log level

application.yml of Ebuy consumer order

server:
  port: 9013 #Port number
  address: 127.0.0.1
  tomcat:
    max-threads: 10 #Maximum number of threads (200 by default)

spring:
  application:
    name: ebuy-order #service name
  cloud:
    consul:
      host: 127.0.0.1 #Specify the consumer service address
      port: 8500 #Specify the consumer service port number
      discovery:
        register: true #Register
        instance-id: ${spring.application.name}-1 #Specify the instance id name
        server-name: ${spring.application.name} #Service instance name
        port: ${server.port} #Service instance port number
        health-check-path: /actuator/health  #Health detection path
        health-check-interval: 15s #Specify the health test interval
        prefer-ip-address: true #Enable ip address registration
        ip-address: ${spring.cloud.client.ip-address} #Instance request ip
        health-check-url: http://${server.address}:${server.port}/**/health
        health-check-critical-timeout: 30s #How many seconds will the service be rejected after the check fails

#Print log
logging:
  level:
    com.ebuy: DEBUG

Add the related configuration of the consumer in spring.cloud.consumer:

  • host: indicates the request address of the Consul Server
  • Port: indicates the port of the Consul Server
  • Discovery: configuration related to service registration and discovery
    • Instance id: the unique id of the instance (required for recommendation) and the recommendation of the spring cloud official website document. In order to ensure that a unique id is generated, it can also be replaced by ${spring.application.name}:${spring.cloud.client.ipAddress}
    • Preferred ip address: enable ip address registration
    • ip address: the request ip address of the current microservice

Start two microservices: view the Consul monitoring center

Microservice based discovery:
Because the spring cloud encapsulates Consul. For obtaining service provider information on the consumer side, it is consistent with Eureka. Similarly, use the DiscoveryClient to complete the call to obtain the micro service instance information, and the other usages are basically consistent with Eureka.

4. Ribbon: client based service invocation (load balancing)

After the above learning, service registration and service discovery have been realized. When a service is started, the information can be registered in the registry through HTTP, and the service list of the registry can be obtained through the tools provided by spring cloud. However, there are still many problems in the call between services, such as how to call micro services more conveniently, how to select multiple micro service providers, how to load balance and so on.

4.1 what is Ribbon?

Ribbon is a load balancer released by Netflix, which helps to control HTTP and TCP client behavior. In spring cloud, Eureka is generally used in conjunction with ribbon. Ribbon provides the function of client load balancing. Ribbon uses the service information read from Eureka or Consul to reasonably load when calling the services provided by the service node, The default is polling policy.

In spring cloud, the registration information can be used together with the Ribbon. The Ribbon automatically obtains the list information of service providers from the registry and requests services based on the built-in load balancing algorithm.

4.2 main functions of Ribbon

Client service call:

  • The implementation of service call based on Ribbon is a mapping relationship composed of all pulled service lists (Service Name: request path), and the call is finally realized with the help of RestTemplate.

Load balancing:

  • When there are multiple service providers, Ribbon can automatically select the service address to be called according to the load balancing algorithm.

4.3 key components of Ribbon

  • ServerList: a list of servers that can respond to a specific service of the client.
  • ServerListFilter: a filter that can dynamically obtain a list of candidate servers with the required characteristics.
  • ServerListUpdater: used to perform dynamic server list updates.
  • Rule: load balancing policy, used to determine which server is returned from the server list.
  • Ping: the client is used to quickly check whether the server is active at that time.
  • LoadBalancer: load balancer, which is responsible for the management of load balancing scheduling.

4.4 engineering transformation

As explained above, Consul replaces Eureka. Here, we temporarily change the registration center to Eureka registration and configure two registration center clusters:
Application.yml (register 8000 to 9000), mutual registration, application.yml (register 9000 to 8000)

server:
  port: 8000 #Port number

spring:
  application:
    name: eureka-server #eurekaServer service name

eureka:
  #instance:
    #hostname: 127.0.0.1 #server ip address 
  client:
    register-with-eureka: true #Register yourself with the registry
    #fetch-registry: false #Get service list from registry
    serviceUrl: #Configure the request address exposed to Eureka Client
      defaultZone: http://127.0.0.1:9000/eureka/
  server:
    enable-self-preservation: false #Turn off the self-protection mechanism (once the service with unstable network is found, it will be eliminated directly)
    eviction-interval-timer-in-ms: 4000 #Elimination interval, unit: ms
    #wait-time-in-ms-when-sync-empty: 5

Service providers and consumers: modify the registry configuration in the application.yml file:

server:
  port: 90XX #Port number
  address: 127.0.0.1
  tomcat:
    max-threads: 10 #Maximum number of threads (200 by default)

spring:
  application:
    name: ebuy-XXXX #service name
#  cloud:
#    consul:
#      host: 127.0.0.1 #Specify the consumer service address
#      port: 8500 #Specify the consumer service port number
#      discovery:
#        register: true #Register
#        instance-id: ${spring.application.name}-1 #Specify the instance id name
#        server-name: ${spring.application.name} #Service instance name
#        port: ${server.port} #Service instance port number
#        health-check-path: /actuator/health  #Health detection path
#        health-check-interval: 15s #Specify the health test interval
#        prefer-ip-address: true #Enable ip address registration
#        ip-address: ${spring.cloud.client.ip-address} #Instance request ip
#        health-check-url: http://${server.address}:${server.port}/**/health
#        health-check-critical-timeout: 30s #How many seconds will the service be rejected after the check fails

#Using the eureka registry
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8000/eureka/,http://127.0.0.1:9000/eureka/
  instance:
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
    prefer-ip-address: true   #Register with ip address (display name in registration center as ip address)
    lease-expiration-duration-in-seconds: 10 #After the eureka client sends the heartbeat to the eureka server server, the renewal expiration time (90 seconds by default)
    lease-renewal-interval-in-seconds: 5 #Send heartbeat renewal interval

#Print log
logging:
  level:
    com.ebuy: DEBUG

4.5. Service call Ribbon advanced, what is load balancing?

When building a website, if the web service performance and reliability of the node can not meet the requirements, or when using the Internet service, they often worry about being attacked, and the Internet port will be opened accidentally. Usually, adding load balancing at this time can effectively solve the service access problem.

Load balancing is a basic network service. Its principle is to distribute the traffic to the back-end service cluster according to the specified load balancing algorithm through the previous load balancing service, so as to provide the system with the ability of parallel expansion.

The application scenarios of load balancing include traffic packets, forwarding rules and back-end services. Because the services have internal and external network cases, health inspection and other functions, they can effectively improve the security and reliability of the system.

4.6. Client load balancing and server load balancing

Client load balancing:

  • The client will obtain the server address list of a service provider from the registry, select a server through the load balancing algorithm before sending the request, and then access it. This is client load balancing, that is, load balancing algorithm allocation is carried out at the client.

Server load balancing:

  • First send the request to the load balancing server or software, and then select one of the multiple servers for access through the load balancing algorithm; That is, the service is allocated in the server through the equalization algorithm

4.7 load balancing based on Ribbon

Firstly, the multi state server should be installed. The above cluster of Eureka registration center has been built, and then two Ebuy products and one Ebuy order can be built, as follows:

1. Service provider Ebuy product

Service provider: modify the ProductController#findById() method under the Ebuy product module:

@RestController
@RequestMapping("/product")
public class ProductController {

	/**
	 * Go back to the client ip address
	 */
	@Value("${spring.cloud.client.ip-address}")
	private String ip;

	/**
	 * Gets the port number of the client
	 */
	@Value("${server.port}")
	private String port;

	@Autowired
	private EasybuyProductService productService;

	@RequestMapping(value = "/{id}",method = RequestMethod.GET)
	public EasybuyProduct findById(@PathVariable Long id) {
		EasybuyProduct product = productService.selectByPrimaryKey(id);
		product.setEpDescription("call ebuy-product service,ip:"+ip+",Service provider port:"+port);
 		return product;
	}
}

Ebuy product service provider starts two sets: 90119012
Ebuy order service consumer starts one: 9013

2. Service consumer Ebuy order

Then create the RestTemplate method at the ebuyordapplication startup class of Ebuy order and add the @ LoadBalanced annotation to realize load balancing with the Ribbon:

@SpringBootApplication
@EnableEurekaClient  //Open Eureka client service registration
@EnableDiscoveryClient  //Turn on service discovery
public class EbuyOrderApplication {

    /**
     * @Bean Configure RestTemplate to spring management
     * @LoadBalanced Load balancing (Ribbon principle)
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

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

Add the order placing method under OrderController of Ebuy order service module:

	@Autowired
    RestTemplate restTemplate;

    
    @RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
    public EasybuyProduct findById(@PathVariable Long id) {
        EasybuyProduct easybuyProduct=new EasybuyProduct();
        //easybuyProduct=restTemplate.getForObject("http://127.0.0.1:9011/product/"+id,EasybuyProduct.class);

        /**
         * Ribbon Load balancing strategy
         * The @ LoadBalanced annotation should be used at the Bean instance registered in RestTemplate,
         * At this time, when restTemplate calls the product Restful API interface, it needs to call the commodity micro service name (to achieve load balancing, the default is polling mechanism)
         */
        easybuyProduct=restTemplate.getForObject("http://ebuy-product/product/"+id,EasybuyProduct.class);
        return easybuyProduct;
    }

Visit the registry address bar localhost:8000:

3. Testing

First, test Ebuy product to query the product information and access the address bar: http://localhost:9011/product/830972 :

Call Ebuy product through the Ebuy order service to see if load balancing can be achieved,
First visit: http://localhost:9013/order/buy/830972

Second visit: http://localhost:9013/order/buy/830972


In the above description, load balancing has been implemented internally, and the RoudrobinBalanced polling policy is still adopted by default

4.8 load balancing strategy

Ribbon has built-in multiple load balancing strategies. The top-level interface responsible for load balancing is com.netflix.loadbalancer.IRule. The implementation method is as follows:

  • Polling policy: com.netflix.loadbalancer.roundrobin rule
  • Random policy: com.netflix.loadbalancer.RandomRule
  • Retry policy: com.netflix.loadbalancer.RetryRule
  • Weight policy: com.netflix.loadbalancer.WeightedResponseTimeRule
    • Calculate the weight of each service. The higher the weight, the greater the possibility of being called
  • Best strategy: com.netflix.loadbalancer.BestAvailableRule
    • Traverse all service instances, filter out fault instances, and return the instance with the smallest number of requests.
  • Filterable policy: com.netflix.loadbalancer.availabilityfiltering rule
    • Filter out the service instances whose failures and requests exceed the threshold, and then poll the calls from the remaining instances

Modify the load balancing policy in the application.yml configuration file of the service consumer Ebuy order:

#The name of the micro service to be called (Ebuy order calls the Ebuy product service)
ebuy-product:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #Adopt random access mechanism (polling mechanism by default)

Policy selection:

  • If the configuration of each server is basically the same, it is not recommended to modify the policy (polling policy is recommended by default)
  • If the part and its configuration are strong, it can be modified to weight policy: WeightedResponseTimeRule

5. Service call Feign

5.1 introduction to Feign service

	@Autowired
    RestTemplate restTemplate;

    @RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
 
    public EasybuyProduct findById(@PathVariable Long id) {
        EasybuyProduct easybuyProduct=new EasybuyProduct();
        
		easybuyProduct=restTemplate.getForObject("http://ebuy-product/product/"+id,EasybuyProduct.class);
        return easybuyProduct;
    }

The RestTemplate we used earlier implements the REST API interface call. It can be seen from the code that we construct the URL by splicing strings, and the URL has only one parameter. However, in reality, URLs often contain multiple parameters. At this time, if we still construct the URL in this way, it is not appropriate. How should we solve it? Feign came out at this time.

5.2 introduction to Feign

Feign is a declarative and templated HTPT client request developed by Netflix. It is inspired by Retrofit,JAXRS-2.0 and WebSocket.

  • Feign can help us call HTTP API interface more conveniently and gracefully
  • In spring cloud, using Feign is very simple. Create an interface and add @ FeignClient annotation on the interface, and the code is finished
  • Feign supports a variety of annotations, such as feign's own annotations or JAX-RS annotations
  • Spring cloud has enhanced Feign so that Feign supports spring MVC annotations, integrates Ribbon and Eureka, and integrates Ribbon and Eureka. This makes Feign more convenient to use

5.3. Feign based service invocation

(1) Introducing dependencies on service callers

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

(2) The EbuyOrderApplication startup class enables Feign support

@SpringBootApplication
@EnableEurekaClient  //Open client service registration
@EnableDiscoveryClient  //Turn on client service discovery
@EnableFeignClients  //Activate feign declarative call
public class EbuyOrderApplication {

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

Enable the Spring Cloud Feign support function through the @ EnableFeignClients annotation.

(3) create a Feign interface, which is the core interface to invoke micro service in Feign:
OrderFeignClient

/**
 * feign here represents a declarative call
 * name: Service name for commodity micro service (cannot be wrong)
 */
@FeignClient(name="ebuy-product")
public interface OrderFeignClient {

    /**
     * The Restful API interface of the product microservice is called here
     * @param id
     * @return
     */
    @RequestMapping(value = "/product/{id}",method = RequestMethod.GET)
    public EasybuyProduct findById(@PathVariable("id") Long id);

}
  • When defining parameter bindings, @ PathVariable, @ Requestparam, @ RequestHeader, etc. can specify parameter properties. In Feign, the binding parameters must specify the specific parameter name through the value attribute, otherwise an exception will be thrown.
  • @FeignCient: the annotation specifies the name of the micro service to be called through name, which is used to create the load balancer of the Ribbon. Therefore, Ribbon will resolve Ebuy product to the service of the registry.

(4) Configure the calling interface of the request provider

@RestController
@RequestMapping("/order")
@SuppressWarnings("all")
public class OrderController {

    /**
     * feign Declarative call
     */
    @Autowired
    OrderFeignClient orderFeignClient;


    /**
     * Call the product microservice Restful API interface declaratively through feign
     * @param id
     * @return
     */
    @RequestMapping(value = "/feign/{id}",method = RequestMethod.GET)
    public EasybuyProduct feignFindById(@PathVariable Long id) {
        return orderFeignClient.findById(id);
    }
}

(5) Restart the service and access the address bar http://localhost:9013/order/feign/830972

That's right!!!

5.4. Contact between Feign and Ribbon

  • Ribbon is a load balancing tool for clients based on HTTP and TCP protocols. It can configure the RibbonServerList (server list) on the client and use HttpClient or RestTmeplate to simulate HTTP requests. The steps are quite cumbersome
  • Feign is modified on the basis of Ribbon. It is a more convenient HTTP client. To adopt the interface method, you only need to create an interface and add annotations on it. You can define the methods of other services to be called as abstract methods without building HTTP requests. Then it is like calling the methods of your own project without feeling that it is calling the methods of remote services, making it very easy for the client.

5.5 Feign load balancing strategy

Feign itself has integrated Ribbon dependency and automatic configuration, so we don't need to introduce additional dependencies or register RestTemplate objects. At the same time, we can also configure the Ribbon in the application.yml file,

  • Global configuration: ribbon.xx
  • Local configuration (specify service name): service name.ribbon.xx

application.yml file of Ebuy order:

#Microservice name to be called (local configuration, specify service name)
ebuy-product:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #Adopt random access mechanism (override the default polling mechanism)
  • The above ribbon.NFLoadBalancerRuleClassName defaults to the polling load balancing policy, which can be modified according to specific circumstances.

We start two Ebuy product service providers 9011 and 9012, and Ebuy order9013 is called declaratively through Feign:
First request address http://localhost:9013/order/feign/830972

Second request address http://localhost:9013/order/feign/830972

It is found that the default round robin rule polling strategy is called declaratively through Feign. Do you think it is strong, Su Daqiang!!!

5.6 Feign advanced service call configuration

Starting with Spring Cloud Edgware, Feign supports customizing Feign using attributes. For a Feign with a specified name
Client (for example, the name of Feign Client is feignName). Feign supports the following configuration items:

#feign declarative call
feign:
  client:
    config:
      feignName : #feignName here represents the name of the service provider to be called
        loggerLevel: FULL #Print all log information
        connectTimeout: 5000  #Equivalent to Request.Options
        readTimeout: 5000 #Equivalent to Request.Options
  • feignName: feignName here represents the name of the FeignClient service provider to be called
  • connectTimeout: the timeout length for establishing the link
  • readTimeout: read timeout duration
  • loggerLevel: log level of Fegin

5.7 request compression

Spring Cloud Feign supports GZIP compression of requests and responses to reduce performance loss during communication. The compression function of request and response can be enabled through the following parameters:

#feign declarative call
feign:
  client:
    config:
      ebuy-product:
        loggerLevel: FULL #Print all log information
        connectTimeout: 5000  #Equivalent to Request.Options
        readTimeout: 5000 #Equivalent to Request.Options
  compression:
    request:
      enabled: true #Turn on request compression
      min-request-size: 2048 #Sets the lower limit of the size that triggers compression
      mime-types: text/html,application/xml,application/json # Set compressed data type
    response:
      enabled: true #Turn on response compression

Note: the above data type and the lower limit of compression size are the default values.

5.8 log level

In the development or running phase, you often want to see the log record of Feign request process. By default, Feign's log is not turned on. To achieve the logging effect through attribute configuration, just add the following content in application.yml:

#The above has been configured
feign:
  client:
    config:
      ebuy-product:
        loggerLevel: FULL #Print all log information

logging:
  level:
    com.ebuy.order.feign.OrderFeignClient: DEBUG
  • Logging.level.xx: debug: Feign logs will only respond to logs with the log level of debug
  • Feign.client.config.ebuy-product.loggerlevel: full: there are four kinds of logs for configuring feign
    Log level:
    • NONE [best performance, suitable for production]: no log is recorded (default value)
    • BASIC [applicable to production environment tracking problem]: only record the request method, URL, response status code and execution time
    • HEADERS: records the header s of requests and responses based on the BASIC level.
    • FULL [more applicable to development and test environment positioning]: record the header, body and metadata of requests and responses.

6. Service registration and discovery summary

6.1 Registration Center

(1)Eureka

  • Build a registration center (server)
    • Introduce the dependency spring - cloud starter Netflix Eureka server
    • Configure EurekaServer
    • Mark the startup class through the @ EnableEurekaServer annotation to activate the Eureka Server side configuration
  • Service registration (client)
    • The service provider introduces the spring - cloud starter Netflix Eureka client dependency
    • Configure the registry address through eureka.client.serviceUrl.defaultZone

(2)Consul

  • Build a registration center (server)
    • Download and install consumer
    • Start consumer, command: consumer agent - dev - client: 0.0.0.0
  • Service registration (client)
    • The service provider introduces the spring - cloud starter consumer discovery dependency
    • Spring.cloud.consumer.host: set the request address
    • Spring.cloud.consumer.port: set request port

6.2. Service call

(1)Ribbon

  • For service calling through Ribbon and RestTemplate, you only need to add the annotation @ LoadBalanced on the method of creating RestTemplate
  • The load balancing policy can be configured through the service name. ribbon.NFLoadBalancerRuleClassName

(2)Feign

  • Service consumers introduce spring cloud starter openfeign dependency
  • Activate Feign declaration through @ EnableFeignClients on startup class
  • Declare an interface to call remote microservice through @ FeignClient

7. Hystrix: service degradation

7.1 avalanche effect

In the microservice architecture, it is very common to call multiple services in A request. For example, when the client accesses service A, service A needs to call service B, and service B needs to call service C. due to network reasons or its own reasons, if service B or service C cannot respond in time, service A will be blocked until service B or service C completes the response. At this time, if A large number of A service requests flood in, the thread resources of the container will be consumed, resulting in system service paralysis. Due to the dependence between services, faults will spread, cause chain reactions, and cause disastrous and serious consequences for the whole microservice system, which is the avalanche effect of service faults.

The butterfly effect in the avalanche effect system is caused by a variety of reasons:

  • Unreasonable capacity design
  • The response of a method becomes slow under high concurrency
  • A machine is running out of resources

We cannot prevent the avalanche effect from the source, but the root cause of the avalanche comes from the strong dependence between services, so we can make an assessment in advance and do a good job in fusing, isolation and current limiting.

1. Service fuse degradation

The concept of fusing comes from the Circuit Breaker in electronic engineering. In the Internet system, when the downstream service responds slowly or fails due to excessive access pressure, the upstream service can temporarily cut off the call to the downstream service in order to protect the overall availability of the system (A). This measure of sacrificing the part and preserving the whole is called fusing.

The so-called degradation means that when a service is blown, the server will no longer be called. At this time, the client can prepare a local fallback method to callback and return a default value, which can also be understood as telling the truth.

2. Service isolation

As the name suggests, it means that the system is divided into several service modules according to certain principles, and each module is independent of each other without strong dependence. When a fault occurs, it can isolate the problem and impact within a module without spreading the risk, affecting other modules and affecting the overall system service.

3. Service current limiting

Current limiting can be considered as a kind of service degradation. Even if current limiting limits the input and output flow of the system to achieve the purpose of protecting the system, generally speaking, the throughput of the system can be budgeted. In order to ensure the stable operation of the system, once the threshold value to be limited is reached, it is necessary to limit the flow and take a few measures to complete the purpose of limiting the flow. For example, postpone settlement, refuse settlement, or partially refuse settlement, etc.

7.2 introduction to Hystrix


Hystrix is a delay and fault tolerance library open source by Netflix. It is used to isolate access to remote systems, services or third-party libraries to prevent cascading failures, so as to improve system availability and fault tolerance. Hystrix mainly realizes delay and fault tolerance through the following points.

  • Wrap request: use HystrixCommand to wrap the calling logic of the dependency. Each command is executed in a separate thread. This uses the command mode in design mode.
  • Trip mechanism: when the error rate of a service exceeds a certain threshold, Hystrix can automatically or manually trip and stop the request for the service for a period of time.
  • Resource isolation: Hystrix maintains a small thread pool (or semaphore) for each dependency. If the thread pool is full, the request for the dependency will be rejected immediately instead of queuing, so as to speed up the failure determination.
  • Monitoring: Hystrix can monitor the changes of operation indicators and configurations in near real time, such as success, failure, timeout and the number of rejected requests.

7.3. Rest request implementation service

We are still based on the above project.

(1) In the Ebuy order service caller pom file, configure the dependency

<!--hystrix Fuse degradation dependency-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

(2) Open fuse support
Add the annotation @ enablercircuitbreaker on the startup class ebuyordapplication to enable support

@SpringBootApplication
@EnableEurekaClient  //Open Eureka client service registration
@EnableDiscoveryClient  //Turn on service discovery
@EnableFeignClients  //Activate feign declarative call
@EnableCircuitBreaker //Open fuse support
//@SpringCloudApplication
public class EbuyOrderApplication {

    /**
     * @Bean Configure RestTemplate to spring management
     * @LoadBalanced Load balancing (Ribbon principle)
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

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

It can be seen that there are more and more annotations on our classes. In microservices, the above common annotations are often introduced, so Spring provides a composite annotation: @ SpringCloudApplication, but it is not recommended to use this composite annotation. Mark the annotations used at the startup class, You can clearly know which technology stack operations are currently used by microservices.

(3) Configure fuse degradation business logic (local fuse method)

@RestController
@RequestMapping("/order")
@SuppressWarnings("all")
public class OrderController {

    @Autowired
    RestTemplate restTemplate;

    /**
     * Call directly across projects through RestTemplate (load balancing can be realized)
     * @PathVariable Map the parameter id in restful to the formal parameter list
     * @HystrixCommand(fallbackMethod = "orderFallBack") Fuse degradation
     */
    @RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
    @HystrixCommand(fallbackMethod = "orderFallBack")
    public EasybuyProduct findById(@PathVariable Long id) {
    	//Manufacturing abnormal fuse degradation
        if(id != 738388){
            throw new RuntimeException("Exception occurred in the request, please try again!");
        }
        return restTemplate.getForObject("http://ebuy-product/product/"+id,EasybuyProduct.class);
    }

    /**
     * Degradation method
     * @param id When using global service degradation processing, the degradation processing function orderFallBack cannot have parameters
     * @param id When using local fusing, the parameters and return value types of the fallback method must be consistent with those of the method to be degraded
     * @param @PathVariable Long id
     */
    public EasybuyProduct orderFallBack(@PathVariable Long id) {
        System.out.println("Fuse:Trigger degradation method");
        EasybuyProduct easybuyProduct = new EasybuyProduct();
        easybuyProduct.setEpDescription("Fuse:Trigger degradation method");
        return easybuyProduct;
    }

}

As can be seen from the above code, on the findById() method, use the fallbackMethod attribute of the annotation @ HystrixCommand to specify that the degradation method triggered by fusing is orderFallBack().

Write a fallback method orderFallback for findById() method below. This method has the same parameters and return value type as findById. This method returns a default error message.

  • The degraded logical method of the local method must guarantee the same parameter list and return value declaration as the normal logical method.
  • Mark @ HystrixCommand(fallbackMethod = "orderFallBack") on the findById() method to declare a method of degrading logic.

(4) Test local fuse
Access address http://localhost:9013/order/buy/738388 Normal display:

At this time, we can shut down the Ebuy product service provider directly in order to test the trigger fuse degradation, but for the convenience of demonstration, we have created a runtime exception in the program in advance in the above findById() code, as long as id= 738388 will throw an exception to simulate the slave operation of the service terminal. Let's enter an id value to access the address localhost:9013/order/buy/11111

(5) Global fuse
As mentioned above, we write fallback on a business method. Obviously, this is not appropriate. If there are many business methods, we need to write many fallback callback methods. Therefore, we can configure fallback on the class to implement the default fallback method. We call it Global:

@RestController
@RequestMapping("/order")
@SuppressWarnings("all")
@DefaultProperties(defaultFallback = "orderFallBack")  //Global fuse degradation
public class OrderController {
    @Autowired
    RestTemplate restTemplate;
    
    /**
     * Call directly across projects through RestTemplate (load balancing can be realized)
     * @PathVariable Map the parameter id in restful to the formal parameter list
     * @HystrixCommand(fallbackMethod = "orderFallBack") Fuse degradation
     */
    @RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
    @HystrixCommand
    public EasybuyProduct findById(@PathVariable Long id) {

        //Manufacturing abnormal fuse degradation
        if(id != 738388){
            throw new RuntimeException("Exception occurred in the request, please try again!");
        }

        return restTemplate.getForObject("http://ebuy-product/product/"+id,EasybuyProduct.class);

    }


    /**
     * Degradation method
     * @param id When using global service degradation processing, the degradation processing function orderFallBack cannot have parameters
     * @param id When using local fusing, the parameters and return value types of the fallback method must be consistent with those of the method to be degraded
     * @param @PathVariable Long id
     */
    public EasybuyProduct orderFallBack() {
        System.out.println("The global fuse is blown:Trigger degradation method");
        EasybuyProduct easybuyProduct = new EasybuyProduct();
        easybuyProduct.setEpDescription("The global fuse is blown:Trigger degradation method");
        return easybuyProduct;
    }

}

Modifications made:

  • Mark @ DefaultProperties(defaultFallback = "orderFallBack") on the OrderController class
  • Mark @ HystrixCommand ID on the business logic method to be processed
  • Note: the orderFallBack() method cannot have a parameter list, but the return value must be consistent with the return value type of the method (in fact, this design is not perfect. There are several methods in a Controller class, but all methods cannot keep the same return value, so it has limitations)

Test, access the address bar id and enter: http://localhost:9013/order/buy/22222

(6) Timeout setting
In the previous case, there is an implied condition that the request will return an error message after more than 1 second (that is, fuse degradation processing will occur). This is because the default timeout of Hystix is 1 second. We can modify this value through configuration:

#hystrix thread request timeout (MS)
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000  #The default is 1 second

We use the request method findById() of the ProductController layer of Ebuy product to simulate the request timeout, let its thread wait for 2 seconds, and then call the findById method of Ebuy product through Ebuy order:

@RestController
@RequestMapping("/product")
public class ProductController {

	/**
	 * Go back to the client ip address
	 */
	@Value("${spring.cloud.client.ip-address}")
	private String ip;

	/**
	 * Gets the port number of the client
	 */
	@Value("${server.port}")
	private String port;

	@Autowired
	private EasybuyProductService productService;

	@RequestMapping(value = "/{id}",method = RequestMethod.GET)
	public EasybuyProduct findById(@PathVariable Long id) {

		//The manufacturing thread sleeps for 2 seconds
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		EasybuyProduct product = productService.selectByPrimaryKey(id);
		product.setEpDescription("call ebuy-product service,ip:"+ip+",Service provider port:"+port);
 		return product;
	}
}

Restart the Ebuy product service, change the port number to 9012, and access it by yourself first, http://localhost:9012/product/738388 :

Enter the correct id through Ebuy order to access the address localhost:9013/order/buy/738388:

You will find that fuse degradation always occurs regardless of access. This is because the default request timeout of hystrix mentioned above is 1 second. Now we set it to 3 seconds through configuration:

#hystrix thread request timeout (MS)
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000  #The default is 1 second. The time is too short. It is set to 3 seconds here

Restart the Ebuy order service and visit the address localhost:9013/order/buy/738388 again

7.4 Feign realizes service fusing

Spring cloud Feign has integrated hystrix internally, so after adding Feign related dependencies, there is no need to add hystrix related dependencies separately. Then how can Feign's circuit breaker mechanism take effect? Just follow the following steps:

(1) Modify the application.yml in Ebuy order service and enable the support of hystrix in Fegin. Although hystrix is integrated in feign, the default timeout setting still needs to be configured separately through the hystrix node:

#feign declarative call
feign:
  hystrix:
    enabled: true #Turn on the hystrix fuse in feign

Hystrix will not be configured temporarily, but the default 1 second of hystrix will be used first.

(2) Configure the OrderFeignClient interface and add the degradation method in the @ FeignClient annotation

@FeignClient(name="ebuy-product",fallback = OrderFeignClientFallBack.class)
public interface OrderFeignClient {

    /**
     * The Restful API interface of the product microservice is called here
     * @param id
     * @return
     */
    @RequestMapping(value = "/product/{id}",method = RequestMethod.GET)
    public EasybuyProduct findById(@PathVariable("id") Long id);

}

(3) Configure the implementation class OrderFeignClientFallBack of the OrderFeignClient interface

@Component
public class OrderFeignClientFallBack implements OrderFeignClient {
    /**
     * Degradation method
     */
    public EasybuyProduct findById(Long id) {
        System.out.println("feign Fuse:Trigger degradation method");
        EasybuyProduct easybuyProduct = new EasybuyProduct();
        easybuyProduct.setEpDescription("feign Fuse:Trigger degradation method");
        return easybuyProduct;
    }
}


Modify the hystrix default time in the application.yml file

#hystrix thread request timeout
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000  #The default is 1 second. The time is too short. It is set to 3 seconds here

Restart the Ebuy order service and re access the address: http://localhost:9013/order/feign/738388

Posted by rockofaith on Mon, 20 Sep 2021 05:39:39 -0700