springcloud summary on

First, the system architecture and evolution

With the development of the Internet, Web applications continue to expand the scale, the surge in demand, followed by a technical pressure. System architecture and therefore continue to evolve, upgrade, iteration. From a single application, to split vertically, the distributed services to the SOA, and now the hot micro service architecture.

1, a centralized architecture

When the site traffic is small, only one application, all the features are deployed together to reduce costs and deploy nodes.

① advantages:

The system development speed Low maintenance costs Requirements for low concurrency system

② Disadvantages:

Code Coupling high, late and difficult to maintain can not be optimized for different modules The level can not be extended The single point fault-tolerance is low, poor concurrency

2, vertical split

When the traffic gradually increased, a single application can not meet the demand, this time to cope with higher concurrency and business needs, we split the system according to business functions:

① advantages:

The split system implements traffic sharing, to solve the problem of concurrency The module can be optimized for different convenient horizontal scaling, load balancing, fault tolerance rate increase

② Disadvantages:

The inter-system independent of each other, there will be a lot of duplication of development work, affecting the development efficiency

3, distributed services

As more and more vertical applications, the inevitable interaction between applications, will be drawn out of the core business, as an independent service, and gradually form a stable center services to enable front-end applications to more quickly respond to changing market demands. At this point, calling for increasing the distributed service multiplexing and integration is the key.

① advantages:

The basic services were extracted, call each other between systems to improve the efficiency of development and code reuse

② Disadvantages:

The coupling system between high, calling relations are complicated, difficult to maintain

4, service management (SOA)

SOA (Service Oriented Architecture) Service-oriented architecture: it is a design methodology which includes multiple services, and ultimately provide a range of functions between service through interdependence. A service normally present in the operating system processes in an independent form. Between the various service calls through the network.

SOA Disadvantages:Each ESB product suppliers are biased, self-realization is more complicated; application service granularity larger, integrated ESB integration of all services and protocols, data conversion makes operation and maintenance, testing, deployment difficult. All services through a communication path, the communication speed is reduced directly.

5, slightly Service

The micro-service architecture is to use the service to develop a small way a single application or approach, each service based on a single operational capacity building, runs in its own process, and the use of lightweight communication mechanism, usually HTTP API, and independent deployment can be automated through the deployment mechanism. These services may use different programming language, as well as different data storage technologies, and to maintain a minimum of centralized management.

① micro-services structure:

② micro-service features:

Ⅰ single responsibility: micro-services Each service corresponds to a unique business ability, so single responsibility Ⅱ oriented service: service-oriented is to say each service to be exposed to the external service interface API. We do not care about technology services, has nothing to do with the platform and language, is not limited by what technology, as long as REST interface can be. Ⅲ Autonomy: Autonomy is to say between services independent of each other without disturbing each other Ⅳ team Independent: Each service is a separate development team. Ⅴ technology-independent: because it is service-oriented, providing REST interface, what technology does not interfere with others Ⅶ before and after the end of the separation: The separation of front and back end development, to provide a unified REST interface, backend no longer need a PC, mobile segment development of different interfaces Ⅷ database separation: Each service uses its own data sources

③ micro-services and SOA comparison:

Second, the remote invocation

Whether or micro-services SOA, are faced with long-distance calls between services. Then the remote invocation room service, what does?

1, common remote calls in the following ways:

①RPC:

Remote Procedure Call Remote Procedure Call, there are similar RMI. Custom data formats, native TCP-based communication, high speed and efficiency. Early Web Service, now popular Dubbo, RPC is typical.

②HTTP:

HTTP is actually a network transmission protocol, based on TCP, it specifies the format of data transmission. Now the client browser and server communications are basically using the HTTP protocol. It can also be used for remote service call. The disadvantage is that encapsulation message bloated. Now popular REST style, can be achieved through the HTTP protocol.

2, know RPC

RPC, i.e., Remote Procedure Call (RPC), is a computer communication protocol. The agreement allowed to run on a single computer program calls a subroutine on another computer, but programmers without additional programming for this interaction. Put it plainly is: A computer provides a service, B Computer A computer can call the service as like to call a local service.

①RPC call flow diagram:

② understanding of HTTP

HTTP is actually a network transmission protocol, based on TCP, working at the application layer defines the format of data transmission. Now the client browser and server communicate using the HTTP protocol basically, it can also be used for remote service call. The disadvantage is that messages are encapsulated bloated, the advantage is to provide the service and the caller does not have any technical limited, freedom and flexibility, more in line with the concept of micro-services. Now popular REST style, can be achieved through the HTTP protocol.

3, how to choose?

RPC mechanism is based on the language of the API (language API) to define, rather than be defined according to the network-based applications. If your company all use Java technology stack, then the use of Dubbo as micro-services architecture is a good choice. Conversely, if the company’s diverse technology stack, and you prefer Spring family, then Spring Cloud to build a micro-service is the best choice. Spring Cloud suite will choose, so you would use HTTP ways to achieve inter-service calls.

The three, Spring Cloud Profile

1 Introduction

Spring Cloud is one of Spring’s project, the official website address:http://projects.spring.io/spring-cloud/ Spring best is to integrate the world’s best framework to take over, into their own projects. Spring Cloud is the same, it is now very popular in some of the technology integration together to achieve such as: configuration management, service discovery, intelligent routing, load balancing, fuses, control bus, cluster status and more. The main assembly includes: ①Netflix ②Eureka: Registry ③Zuul: Services Gateway ④Ribbon: Load Balancing ⑤Feign: service call ⑥Hystrix: Fuse These are just a part of composition:

2, version

Spring Cloud version name is rather special, because it is not a component, but a collection of many components, and its name is based on the letters A to Z, led by a few-word (in fact, is the name of the London Underground station):

Spring Clound and Spring Boot correspondence between the versions

The course uses Greenwich version

Fourth, the micro-services scenario simulation

1, create the parent project lxs-springcloud

Micro Services need to create multiple projects, in order to facilitate classroom presentations, create a parent project, the follow-up project to this project are the parent, using Maven aggregation and inheritance. Unified management of the sub-project version and configuration

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.lxs</groupId>
   <artifactId>lxs-springcloud</artifactId>
   <-! Aggregation parent project using maven ->
   <packaging>pom</packaging>
   <version>1.0-SNAPSHOT</version>

   <-! Greenwich correspond with spring-boot version of 2.1.x, 2.1.5 here ->
   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.1.5.RELEASE</version>
       <relativePath/>
   </parent>

   <properties>
       <java.version>1.8</java.version>
       <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
       <! - introducing tk-mybatis ->
       <mapper.starter.version>2.1.5</mapper.starter.version>
       <! - introducing mysql ->
       <mysql.version>5.1.46</mysql.version>
   </properties>

   <dependencyManagement>
       <dependencies>
           <!-- springCloud -->
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-dependencies</artifactId>
               <version>${spring-cloud.version}</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
           <-! Universal Mapper Launcher ->
           <dependency>
               <groupId>tk.mybatis</groupId>
               <artifactId>mapper-spring-boot-starter</artifactId>
               <version>${mapper.starter.version}</version>
           </dependency>
           <-! Mysql Driver ->
           <dependency>
               <groupId>mysql</groupId>
               <artifactId>mysql-connector-java</artifactId>
               <version>${mysql.version}</version>
           </dependency>
       </dependencies>
   </dependencyManagement>
   <dependencies>
       <! - lombok member is introduced to simplify the development entity class ->
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>
</project>

Note:spring clound和spring boot 的版本对应 greenwich版本clound对应spring boot 2.1.x Note:Pay attention to the parent project<packaging>pom</packaging> been here for most dependent versions were use to manage, easy to use follow-up

2, the service provider

We create a new project, provide access to outside users of the service.

① creation module

Select lxs-springclound, create a sub-project user-service: pom.xml file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <parent>
       <artifactId>lxs-springcloud</artifactId>
       <groupId>com.lxs</groupId>
       <version>1.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>

   <artifactId>user-service</artifactId>

   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <! - Universal Mapper starter ->
       <dependency>
           <groupId>tk.mybatis</groupId>
           <artifactId>mapper-spring-boot-starter</artifactId>
       </dependency>
       <-! Mysql Driver ->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
       </dependency>
   </dependencies>
</project>

② use the tool to generate UserApplication starter

③ write configuration file application.yml

server:
port: 9091
spring:
datasource:
  driver-class-name: com.mysql.jdbc.Driver
  url: jdbc:mysql://localhost:3306/springCloud
  username: root
  password: 123456
# Set the alias search package tk-mybatis
mybatis:
type-aliases-package: com.lxs.user.pojo

④ import springclound.sql

⑤ write entity class User

package com.lxs.user.pojo;

import lombok.Data;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;

@Data
@Table(name = "tb_user")
public class User{
   // id
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
   // Username
   private String userName;
   // password
   private String password;
   // Name
   private String name;
   // Age
   private Integer age;
   // sex, 1 male, 2 females
   private Integer sex;
   // Date of Birth
   private Date birthday;
   // Created
   private Date created;
   // Updated
   private Date updated;
   // Remarks
   private String note;
}

⑥ write UserMapper

package com.lxs.user.mapper;

import com.lxs.user.pojo.User;
import tk.mybatis.mapper.common.Mapper;

public interface UserMapper extends Mapper<User> {
}

⑦ write UserService

package com.lxs.user.service;

import com.lxs.user.mapper.UserMapper;
import com.lxs.user.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
   @Autowired
   private UserMapper userMapper;
   public User queryById(Long id){
       return userMapper.selectByPrimaryKey(id);
  }
}

⑧ write UserController

package com.lxs.user.controller;

import com.lxs.user.pojo.User;
import com.lxs.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {
   @Autowired
   private UserService userService;
   @RequestMapping("/{id}")
   public User queryById(@PathVariable Long id){
       return userService.queryById(id);
  }
}

⑨ automatic injector configuration UserMapper

package com.lxs.user;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;

@SpringBootApplication
@MapperScan("com.lxs.user.mapper")
public class UserApplication {
   public static void main(String[] args) {
       SpringApplication.run(UserApplication.class, args);
  }
}

⑩ commissioning

http://localhost:9091/user/1

Note:

1, automatic closing spring error injection

依次打开Setting——Editor——Inspetions——Spring——Spring Core——Code,将Autowiring for bean class的Severity设置为Warning

3, caller service

① create consumer-demo project

Similar to above, not repeat them here, to note that, we call user-service functions, and therefore do not need to rely on the relevant Mybatis previous copy user-service module, change the coordinate response

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <parent>
       <artifactId>lxs-springcloud</artifactId>
       <groupId>com.lxs</groupId>
       <version>1.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>

   <artifactId>consumer-demo</artifactId>

   <properties>
       <maven.compiler.source>11</maven.compiler.source>
       <maven.compiler.target>11</maven.compiler.target>
   </properties>

   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
   </dependencies>

</project>

② use the tool to generate configuration files and start ConsumerApplication

③ write ConsumerApplication class

package com.lxs.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class ConsumerApplication {
   public static void main(String[] args) {
       SpringApplication.run(ConsumerApplication.class, args);
  }
   @Bean
   public RestTemplate restTemplate(){
       return new RestTemplate();
  }
}

Spring RestTemplate provides a tool template class of client HTTP-based package, and achieves serialization and deserialization of the objects json, very convenient. RestTemplate not limited to HTTP client type, but the abstract, are currently used three kinds of support: Ⅰ HTTPClient Ⅱ OkHTTP Ⅲ JDK URLConnection native (default)

如需使用HttpClient和OkHTTP则需要引入相应的依赖并传入RestTemplate()的参数中

@Bean自动注入对象的名称与方法名一致

④ write deserialize entity class User

package com.lxs.consumer.pojo;

import lombok.Data;
import java.util.Date;

@Data
public class User {
   // id
   private Long id;
   // Username
   private String userName;
   // password
   private String password;
   // Name
   private String name;
   // Age
   private Integer age;
   // sex, 1 male, 2 females
   private Integer sex;
   // Date of Birth
   private Date birthday;
   // Created
   private Date created;
   // Updated
   private Date updated;
   // Remarks
   private String note;
}

⑤ write UserController

package com.lxs.consumer.controller;

import com.lxs.consumer.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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;

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

   @GetMapping("/{id}")
   public User queryById(@PathVariable long id){
       String url="http://localhost:9091/user/"+id;
       return restTemplate.getForObject(url,User.class);
  }
}

⑥ start test

Because we do not have port configuration, the default is 8080, we visited:http://localhost:8080/consumer/1

4, thinking

brief review, just what we wrote: ①user-service: provide external query user interface ②consumer-demo: access by RestTemplatehttp://locahost:9091/user/{id} interface to query the user data exist any problems? Ⅰ the consumer, we have the url address hard-coded into the code, convenient post-maintenance Ⅱconsumer need to remember user-service address, if the change occurs, it may not be notified, the address will fail Ⅲconsumer clear user-service status, service outages do not know only one user-service desk services, do not have high availability even user-service formation of clusters, consumer need their own load balancing In fact, the above said problem, summarize is bound to face problems of distributed services: 1 Service Management How to automatically register and discover I How to implement status supervision IIIIIII implement a dynamic route 2 How to achieve load balancing 3 How to solve disaster disaster problems 4 How to implement a unified configuration The above questions, we will get answers in SpringCloud.

Fifth, Eureka Registration Center

1, EUREKA Introduction

1 Analysis

In the case, the user-service provides services to the outside of the outside. And consumer needs to record the address of the service provider. In the future, the address will change, but also update in time. This doesn’t feel anything when the service is less, but in the increasingly complex internet environment, a project will definitely split a dozen or dozens of micro service. At this time, if you still have a management address, you will not only develop difficulties. In the future, it will be very troublesome, which will be very troublesome, this is a lack of devops.

2 Netmodi

This is like a network of online approaches, people can only call a taxi. Some private cars want to do rental but they are not qualified, known as the black car. And many people want to be a car, but there is too little taxis, it is inconvenient. Private cars are much more darent, and the car is full of streets, who knows which is willing to manal. One wants, one is willing, it is lacking the origin, lacks management. At this time, the net approximation platform like this appeared. All private cars who want to passengers will be registered, record your model (service type), identity information (contact information). This allows the private car to serve, can be found there, and a glimpse. People who want to call the car at this time, only need to open the app, enter your destination, select the model (service type), drip automatically arrange a car to you, serve you, perfect!

What do I doing 212.3eureka?

Eureka is like a drip, responsible for managing, and recording service providers. Service calls do not need to find their own services, but tell Eureka with their needs, and Eureka will tell you the service that meets your needs. At the same time, the service provider and the EUREKA are monitored through the “Heartbeat” mechanism. When a service provider has problems, Eureka will naturally remove it from the service list. This realizes the automatic registration, discovery, status monitoring of services.

2, schematic

Basic architecture:

1Eureka: is the service registration center (can be a cluster), exposing his address 2 Provider: Register your own information to EUREKA after startup (what services provide 3 Consumers: To the EUREKA subscription service, EUREKA will send all the provider addresses of the corresponding service to the consumer and update regularly. 4 Heartbeat (renewal): The provider regularly refreshes its own state to Eureka via HTTP mode

Working principle analysis

3, entry case

1 Write Eurekaserver

Eureka is a service registration center, only service registration; it does not provide service. You can build a web engineering using EUREKA, you can use the Spring Boot to build.

I, write pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <parent>
       <artifactId>lxs-springcloud</artifactId>
       <groupId>com.lxs</groupId>
       <version>1.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>

   <artifactId>eureka-server</artifactId>

   <dependencies>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
       </dependency>
   </dependencies>
</project>

I, write launch class

package com.lxs.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

// Declaration EUREKA service when current application
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
   public static void main(String[] args) {
       SpringApplication.run(EurekaApplication.class, args);
  }
}

III, write Application.yml

server:
port: 10086
spring:
application:
  name: eureka-server
eureka:
client:
  service-url:
     # EUREKA service address, if it is a cluster; you need to specify other cluster Eureka addresses
    defaultZone: HTTP://127.0.0.1:10086/eureka
   # Do not register yourself
  register-with-eureka: false
   # Do not pull service
  fetch-registry: false

IV Launch Service and Access:http://127.0.0.1:10086/

2 Service Registration

Add EUREKA client dependencies on the service provider User-Service; register the service to the EUREKaserver service address list.

I Add dependence

<! - Eureka Client ->
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
       </dependency>

I Open Eureka client function on the startup class

Open the Eureka client function by adding @enablediscoveryclient

package com.lxs.user.controller;

import com.lxs.user.pojo.User;
import com.lxs.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
// Open Eureka Client Discovery Function
@EnableEurekaClient
public class UserController {
   @Autowired
   private UserService userService;
   @RequestMapping("/{id}")
   public User queryById(@PathVariable Long id){
       return userService.queryById(id);
  }
}

IIII modification configuration

server:
port: 9091
spring:
datasource:
  driver-class-name: com.mysql.jdbc.Driver
  url: jdbc:mysql://localhost:3306/springCloud
  username: root
  password: 123456
application:
  name: user-service
# Set TK-MyBatis Alias ​​Search Package
mybatis:
type-aliases-package: com.lxs.user.pojo

eureka:
client:
  service-url:
    defaultZone: HTTP://127.0.0.1:10086/eureka

Note: Here we add a spring.Application.name property to specify the app name, which will be used as an application ID. Don’t specify Register-with-Eureka and Fetch-Registry, because the default is TRUE

IV Restart Project, Access the Eureka Monitor page View

We found that the user-service service has been registered successfully.

3 Service discovery

Add EUREKA client dependencies on the service consumption engineering Consumer-Demo; you can use tool class discoveryclient to get the right address list according to the service name.

I Add dependence

<! - Eureka Client ->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

I In the start-up class, add the annotation of the Eureka client discovery

package com.lxs.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
/ Open Eureka client
@EnableEurekaClient
public class ConsumerApplication {
   public static void main(String[] args) {
       SpringApplication.run(ConsumerApplication.class, args);
  }
   @Bean
   public RestTemplate restTemplate(){
       return new RestTemplate();
  }
}

IIII modification configuration:

spring:
application:
  name: consumer-demo
eureka:
client:
  service-url:
    defaultZone: HTTP://127.0.0.7:10089/eureka

IV to modify the code, use the DiscoveryClient method, obtain the service instance according to the service name:

package com.lxs.consumer.controller;

import com.lxs.consumer.pojo.User;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
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 java.util.List;

@RestController
@RequestMapping("/consumer")
public class UserController {
   @Autowired
   private RestTemplate restTemplate;
   @Autowired
   private DiscoveryClient discoveryClient;

   @GetMapping("/{id}")
   public User queryById(@PathVariable long id){
       String url="http://localhost:9091/user/"+id;
       List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
       ServiceInstance serviceInstance=instances.get(0);
       url="http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/user/"+id;
       return restTemplate.getForObject(url,User.class);
  }
}

V Debug Tracking

Generated URL

Access results

Sixth, EUREKA Detailed

1, infrastructure

Eureka架构中的三个核心角色:

1 Service Registration Center

Eureka’s server application, providing service registration and discovery functions, is the Eureka-Server we have established

2 service provider

The application of the service can be the Spring Boot application, or other techniques are implemented, as long as the external REST style service is available. This example is our User-Service

3 Serving consumers

Consumer Application Gets a list of service from the registration center, thus knowing the information of each serve party, know where to call the service party. This example is the consumer-demo we implemented.

2, EUREKA Server, Highly available

Eureka Server, the service registry, in the case, we have only one EUREKASERVER, in fact Eurekaserver can also be a cluster to form a highly available Eureka Center. Eureka Server is a web application that enables multiple instances (configuring different ports) to ensure that the EUREKA Server is highly available.

1 Service Synchronization

A plurality of EUREKA Server will also be registered as a service. When the service provider registers a node in the EUREKA Server cluster, the node synchronizes the information to each node in the cluster, thereby implementing data Synchronize. Therefore, the full service list information can be obtained regardless of any of the client access to any of the Eureka Server cluster. As a client, register information to each EUREKA

If there are three EUREKA, each EUREKaserver needs to register in several other Eureka services. For example: three are 10086, 10087, 10088, respectively: 10086 To register to 10087 and 10088 10087 To register to 10086 and 10088 10088 To register to 10086 and 10087

2 Hand to build a high available Eurekaserver

We assume that two EUREKaserver’s clusters, ports are: 10086 and 10087

I Modified the original EUREKaserver configuration:

server:
port: ${port:10086}
spring:
application:
  name: eureka-server
eureka:
client:
  service-url:
     # EUREKA service, if you do a cluster, you need to specify other Eureka addresses
    defaultZone: ${defaultZone:http://127.0.0.1:10086/eureka}
# # Do not register yourself
# Register-with-eureka: false
# # Do not pull service
# fetch-registry: false

The so-called high availability registration center is actually registered with EUREKaserver as a service, so many EUREKaserver can find each other to form a cluster. So we made the following modifications: 1, deleting two configurations of register-with-eureka = false and fetch-registry = false. Because the default is TRUE, it will be registered to the registration center. 2, change the value of the service-url into another EUREKaserver address, not yourself

I Dialecting You can specify port port and defaultzone configuration when starting:

Modify the original startup configuration component; in the VM Options in the following interface Set -DDefaultzone = http: 127.0.0.1: 10087 / Eureka

Copy a copy and modify; set -Dport = 10087 in VM Options in the following interface – DdefaultZone=http:127.0.0.1:10086/eureka

3 Launch test; start two Eureka Server

4 Client registration to the cluster

Because the EUREKaserver is more than one, the service-url parameter needs to change when the service is registered:

server:
port: ${port:10086}
spring:
application:
  name: eureka-server
eureka:
client:
  service-url:
     # EUREKA The address of the service, if you do a cluster, you need to specify other Eureka addresses
     # EUREKaserver address, multiple addresses with ','
    defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
# # Do not register yourself
# Register-with-eureka: false
# # Do not pull service
# fetch-registry: false

In order to facilitate the modification of classes and later, you can change back to a single Eureka Server again after testing the above configuration.

3, EUREKA client and server configuration

This section we conduct a range of configurations: Eureka client engineering User-service service Service address uses IP mode Renewal Consumer-Demo service consumption Get the frequency of service addresses Eureka server EUREKA-Server Failure rejection Self-protection The service provider wants to register the EUREKaserver and complete the service renewal.

1 Service Registration

When the service provider is started, the configuration properties are detected: EUREKA.CLIENT.REGISTER-with-ERUEKA = True parameter is TRUE, and it is true that True is true. If the value is indeed true, a REST request is initiated to the EUREKaserver and bring your metadata information, and EUREKaserver saves this information to a double-layer MAP structure. The first layer of MAP’s key is the service ID, which is generally the Spring.Application.name property in the configuration. User-Service The second layer of MAP’s key is the example ID of the service. General Host + Serviceid + Port, for example: localhost: user-service: 8081 The value is the instance object of the service, which means a service, which can start multiple different instances simultaneously to form a cluster. The host name or localhost is used by default. If you want to use IP to register, you can add configured to add in the user-service:

server:
port: 9091
spring:
datasource:
  driver-class-name: com.mysql.jdbc.Driver
  url: jdbc:mysql://localhost:3306/springCloud
  username: root
  password: 123456
application:
  name: user-service
# Set TK-MyBatis alias search package
mybatis:
type-aliases-package: com.lxs.user.pojo

eureka:
client:
  service-url:
    defaultZone: http://127.0.0.1:10086/eureka
instance:
   # ip address
  ip-address: 127.0.0.1
   # more inclined to use IP instead of HOST
  prefer-ip-address: true

After the modification, the user-service and consumer-demo are restarted; it has become an IP address when calling the service; it is necessary to note: not the console service instance status status in EUREKA.

2 Service Renewal

After the registration service is completed, the service provider will maintain a heartbeat (timing to the Eurekaserver REST request), tell Eurekaserver: “I am still alive.” This renewal of our service is called; There are two important parameters to modify the behavior of the service constant; you can add the following configuration items in the user-service:

server:
port: 9091
spring:
datasource:
  driver-class-name: com.mysql.jdbc.Driver
  url: jdbc:mysql://localhost:3306/springCloud
  username: root
  password: 123456
application:
  name: user-service
# Set the TK-MyBatis alias search package
mybatis:
type-aliases-package: com.lxs.user.pojo

eureka:
client:
  service-url:
    defaultZone: http://127.0.0.1:10086/eureka
instance:
   # ip address
  ip-address: 127.0.0.1
   # more inclined to use IP, not HOST name
  prefer-ip-address: true
   # Service failed time, default 90 seconds
  lease-expiration-duration-in-seconds: 90
   # Service Renewal Space, default is 30 seconds
  lease-renewal-interval-in-seconds: 30

Llease-rental-interval-in-seconds: Renendation of Renewal, default is 30 seconds Lease-expression-duration-in-seconds: service failure time, default 90 seconds

That is, by default, each 30 second service will send a heartbeat to the registry, prove that he is still alive. If you don’t send your heartbeat, EUREKAServer will be removed from the service list, which is not modified by the production environment.

3 Get Service List

When the service consumers start, the value of the EUREKA.CLIENT.FETCH-Registry = TRUE parameter is detected. If true, you will pull the read-only backup from the list of EUREKA Server services, and then there is locally. And re-draw and update the data every 30 seconds. You can modify the following parameters in the Consumer-Demo project:

spring:
application:
  name: consumer-demo
eureka:
client:
  service-url:
    defaultZone: HTTP://127.0.0.7:10086/eureka
   # Every 30 seconds, will pull the read-only backup from the list of Eureka Server services, and then the locally is slowed.
  registry-fetch-interval-seconds:  30

In the production environment, we don’t need to modify this value. But in order to develop the service, we can set it a little bit.

4 Failure to eliminate and self-protection

The following configuration is performed at the Eureka Server server:

I Service offline

When the service is turned off, it triggers the REST request for a service offline to EUREKA Server, tells the service registration center: “I want to go online.” After the service center accepts the request, the service is set to the lower line.

II failover

Sometimes our service may make the service not working properly due to memory overflow or network failure, and the service registration center does not receive a request for “service offline”. Compared to the service provider’s “service renewal” operation, the Service Registration Center creates a timing task when starting, the default time (default is 60 seconds), the current list is timeout (default is 90 seconds) without renewal The service is removed, which is called failure. It can be modified by the EUREKA.SERVEER.EVICTION-Interval-Timer-IN-MS parameter, and the unit is milliseconds.

III Self-protection

We shut a service at the EUREKA panel:

This is a self-protection mechanism that triggers EUREKA. When a service does not perform a heartbeat on time, EUREKA will count whether the proportion of service instances of the last 15 minutes of heartbeat failure exceeds 85%, when the EUREKaserver node lost too many clients in a short time (network partition failure) . In the production environment, because of network delay, the proportion of heartbeat failed instances is likely to exceed the standard, but the service exclusion list is not appropriate because the service may not be downtime. EUREKA will protect the registration information of the current instance and do not remove it. This is effective in the production environment, ensuring that most services are still available. But this brings us to our development, so we will close the self-protection model during the development stage:

server:
port: 10086
spring:
application:
  name: eureka-server
eureka:
client:
  service-url:
     # EUREKA service, if you do a cluster, you need to specify other Eureka addresses
    defaultZone: http://127.0.0.1:10086/eureka
# # Do not register yourself
# Register-with-eureka: false
# # Do not pull service
# fetch-registry: False
server:
   # Scan the interval of failover services (default 60 * 1000ms)
  eviction-interval-timer-in-ms: 10000
   # Turn off self-protection mode (the default is open)
  enable-self-preservation: false

5 small knot

I User-Service

server:
port: 9091
spring:
datasource:
  driver-class-name: com.mysql.jdbc.Driver
  url: jdbc:mysql://localhost:3306/springCloud
  username: root
  password: 123456
application:
  name: user-service
# Set TK-MyBatis alias search package
mybatis:
type-aliases-package: com.lxs.user.pojo

eureka:
client:
  service-url:
    defaultZone: http://127.0.0.1:10086/eureka
instance:
   # ip address
  ip-address: 127.0.0.1
   # more inclined to use IP, not HOST name
  prefer-ip-address: true
   # Service invalidation time, default 90 seconds
  lease-expiration-duration-in-seconds: 90
   # Service Renewal (Renew) interval, default is 30 seconds
  lease-renewal-interval-in-seconds: 30

II Consumer-Demo

spring:
application:
  name: consumer-demo
eureka:
client:
  service-url:
    defaultZone: HTTP://127.0.0.7:10086/eureka
   # Every 30 seconds will pull the read-only backup from the list of Eureka Server services, and then there is locally.
  registry-fetch-interval-seconds:  30

III EUREKA-Server

server:
port: 10086
spring:
application:
  name: eureka-server
eureka:
client:
  service-url:
     # Eureka service, if you do a cluster, you need to specify other Eureka addresses
    defaultZone: http://127.0.0.1:10086/eureka
# # Do not register yourself
# Register-with-eureka: false
# # Do not pull service
# fetch-registry: false
server:
   # Scan the interval of failure services (50 * 1000ms by default)
  eviction-interval-timer-in-ms: 10000
   # Turn off self-protection mode (the default is open)
  enable-self-preservation: false

Seven, load balance Ribbon

In the case, we launched a user-service, then obtain the service instance information through DiscoveryClient, then get the IP and port to access. But in the actual environment, we tend to open a number of User-Service clusters. At this point, there will be multiple services in the service list, which one is there? In this case we need to write a load balancing algorithm and select in multiple instance lists. However, EUREKA has helped us integrate load balancing components: Ribbon, simply modify the code.

1, what is Ribbon:

Next, we will use Ribbon to implement load balancing.

2, start two service instances

First we launched two USER-Service instances, one 9091, one 9092. Configure the following ports in User-Service:

server:
port: ${port:9091}

Configure it in the startup configuration as follows

Eureka Monitoring Panel:

3, turn on load balancing

Because Ribbon has been integrated in Eureka, we do not need to introduce new dependencies. Directly modify code: Add @loadbalanced annotation on RESTTEMPLATE configuration:

package com.lxs.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
// Open the Eureka client
@EnableEurekaClient
public class ConsumerApplication {
   public static void main(String[] args) {
       SpringApplication.run(ConsumerApplication.class, args);
  }
   @Bean
   @LoadBalanced
   public RestTemplate restTemplate(){
       return new RestTemplate();
  }
}

Modify the call mode, no longer manually acquire IP and port, but call directly through service name:

package com.lxs.consumer.controller;

import com.lxs.consumer.pojo.User;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
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 java.util.List;

@RestController
@RequestMapping("/consumer")
public class UserController {
   @Autowired
   private RestTemplate restTemplate;
   @Autowired
   private DiscoveryClient discoveryClient;

   @GetMapping("/{id}")
   public User queryById(@PathVariable long id){
// String Url = "http: // localhost: 9091 / user /" + id;
// list <serviceinstance> instances = discoveryclient.getinstances ("user-service");
/////////// Serviceinstance ServiceInstance = Instances.get (0);
// URL = "http: //" + serviceinstance.getHost () + ":" + ServiceInstance.getPort () + "/ user /" + id;
       String url="http://user-service/user/"+id;
       return restTemplate.getForObject(url,User.class);
  }
}

Access page, view Results:

Perfect! Access page, view the results; and you can view the execution at the console of 9091 and 9092:

4, source tracking

Why can I access only the service name? The IP and port are you more before. It is obvious that the component obtains the IP and port of the service instance according to the service name. Because Consumer-Demo uses RESTTTEMPLATE, Spring uses the loadbalancer IntercessPtor interceptor, this class intercepts the request for RESTTEMPLATE, then obtains a list of service from EUREKA, and then uses the load balancing algorithm to get real service address information, replace service ID. We carry out source tracking:

Continue to follow the Execute method: Found 9092 service

Follow the next time, found that the acquisition is 9091:

5, load balancing strategy

Ribbon default load balancing strategy is a simple polling, we can test it: Write the test class. In the source code we just saw that interception is to use RibbonLoadBalanceClient to perform load balancing, with a Choose method, this is this:

Now this is a method of load balancing acquisition instance. We have the object that is injected into this class and then tests:

1 Import test dependence

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
</dependency>

2 Add test method

package com.lxs.consumer.pojo;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class LoadBalanceTest {
   @Autowired
   RibbonLoadBalancerClient client;
   @Test
   public void test(){
       for (int i = 0; i < 100; i++) {
           ServiceInstance instance = this.client.choose("user-service");
           System.out.println(instance.getHost() + ":" + instance.getPort());
      }
  }
}

Result:

In line with our expectations, it is indeed polling.

SpringBoot also helped us with the modification of the configuration entry for load balancing rules:

spring:
application:
  name: consumer-demo
eureka:
client:
  service-url:
    defaultZone: HTTP://127.0.0.7:10086/eureka
   # Every 30 seconds will pull the read-only backup from the list of EUREKA Server services, and then the local isocheated.
  registry-fetch-interval-seconds:  30
user-service:
ribbon:
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

The format is: {service name} .ribbon.nfloadbalancerruleClassName, value is the implementation class of Irule

Test again and found that the result became random: