What is service governance?
Spring Cloud encapsulates the Eureka module developed by Netflix to realize service governance
In the traditional rpc remote invocation framework, it is complex to manage the dependency between each service. Therefore, it is necessary to use service governance to manage the dependency between services. Service invocation, load balancing, fault tolerance, etc. can be realized, and service discovery and registration can be realized!
What is service registration and discovery
Eureka adopts the design architecture of CS. Eureka Server is the server of service registration function, and it is the service registration center. Other microservices in the system use Eureka's client to connect to Eureka Server and maintain heart
Skip connection. In this way, the system maintenance personnel can monitor the normal operation of various services in the system through Eureka Server.
In service registration and discovery, there is a registry. When the server starts, it will register its current server information, such as service address and communication address, in the registry by alias. Other party (consumer) service provision
Get the actual service communication address from the registry in the way of this alias, and then implement the local RPC call. The core design idea of RPC remote call framework: the registry is used to manage each service and service
A dependency between services (service governance concept). In any rpc remote framework, there will be a registry (storing information related to the service address (interface address))
Eureka consists of two components: Eureka Server and Eureka Client
Eureka Server provides service registration services:
After each micro service node is started through configuration, it will be registered in EurekaServer. In this way, the service registry in EurekaServer will store the information of all available service nodes, and the information of service nodes can be seen intuitively in the interface.
EurekaClient is accessed through the registry:
It is a Java client to simplify the interaction of Eureka Server. The client also has a built-in load balancer using round robin load algorithm. After the application starts, a heartbeat will be sent to Eureka Server. The default cycle is 30 seconds. If Eureka Server does not receive the heartbeat of a node in multiple heartbeat cycles, Eureka Server will remove the service node from the service registry (90 seconds by default).
https://www.cnblogs.com/dalianpai/p/12263438.html
We directly use eureka to build a service registration and discovery cluster to realize the function of microservice invocation
1. Create a maven parent project (spring cloud)
<!--unified management jar Package version--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <junit.version>4.12</junit.version> <lombok.version>1.18.10</lombok.version> <log4j.version>1.2.12</log4j.version> <mysql.version>8.0.18</mysql.version> <druid.version>1.1.10</druid.version> <mybatis.spring.boot.version>1.3.2</mybatis.spring.boot.version> </properties> <!--After the sub module inherits, it provides the following functions: locking the version+son module Do not write groupId and version--> <dependencyManagement> <dependencies> <!--spring boot 2.2.2--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.2.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--spring cloud Hoxton.SR1--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR1</version> <type>pom</type> <scope>import</scope> </dependency> <!--spring cloud alibaba--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.1.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> <scope>runtime</scope> </dependency> <!-- druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.spring.boot.version}</version> </dependency> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <!--log4j--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> </dependencies> </dependencyManagement>
2. Create three eureka services (cloud eureka server7001, cloud eureka server7002 and cloud eureka server7003):
Main startup class: the other two will not be posted
@EnableEurekaServer //Indicates that this project is eureka's service registry @SpringBootApplication public class EurekaMain7001 { public static void main(String[] args) { SpringApplication.run(EurekaMain7001.class, args); } }
pom.xml
<dependencies> <!-- eureka-server --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--monitor--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- General configuration --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
application.yml the other two will not be posted. Change the port and defaultZone
server: port: 7001 eureka: instance: hostname: eureka7001.com #Instance name of eureka server client: #false means you don't register yourself with the registry (you can register if you want, but it's not necessary) register-with-eureka: false #false means that the client is the registry, whose responsibility is to maintain service instances and does not need to retrieve services fetch-reapplication.ymlgistry: false service-url: #Setting the address query service and registration service that interact with Eureka server depends on this address #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #Cluster versions register and watch each other defaultZone: http://eureka7002.com:7002/eureka/, http://eureka7003.com:7003/eureka/ # defaultZone is a fixed writing method. If you want to customize it, you need to write it as follows: # region: eureka-server # availability-zones: # eureka-server: server1,server2 # service-url: # server1: http://eureka7002.com:7002/eureka/ # server2: http://eureka7003.com:7003/eureka/ server: #Turn off self-protection. The default value is true enable-self-preservation: false #Heartbeat interval, in milliseconds eviction-interval-timer-in-ms: 2000
Modify the following hosts file:
3. Building consumers and service providers:
3.1. Create an entity middleware project cloud API Commons:
The package path is:
com.cjian.springcloud.bean
public class CommonResult<T> { private Integer code; private String message; private T data; public CommonResult(Integer code, String message, T data) { this.code = code; this.message = message; this.data = data; } public CommonResult(Integer code, String message){ this(code, message, null); } public CommonResult() { } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
public class Payment implements Serializable { private Long id; private String serial; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getSerial() { return serial; } public void setSerial(String serial) { this.serial = serial; } }
3.2. Build two service providers
cloud-provider-payment8001,cloud-provider-payment8002
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>com.cjian.springloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <!-- alibaba of druid Database connection pool --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <!--mysql-connector-java--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.18</version> </dependency> <!--jdbc--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
application.yml
server: port: 8001 spring: application: name: cloud-payment-service datasource: type: com.alibaba.druid.pool.DruidDataSource # Current data source operation type driver-class-name: com.mysql.cj.jdbc.Driver # mysql driver package url: jdbc:mysql://127.0.0.1:3306/mysql?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC username: root password: 123456 mybatis: mapperLocations: classpath:mapper/*.xml type-aliases-package: com.cjian.springcloud.bean # Package of all Entity alias classes eureka: client: register-with-eureka: true fetch-registry: true service-url: #defaultZone: http://localhost:7001/eureka defaultZone: http://eureka7001.com:7001/eureka,http://eureka7001.com:7002/eureka,http://eureka7001.com:7003/eureka instance: instance-id: payment8001 prefer-ip-address: true #The access path can display the ip address #The time interval between Eureka client sending heartbeat to server, unit: seconds (default: 30 seconds) lease-renewal-interval-in-seconds: 1 #The upper limit of waiting time for Eureka server after receiving the last heartbeat, in seconds (90 seconds by default), and the timeout service is excluded lease-expiration-duration-in-seconds: 2
Package path: com.cjian.springcloud
@Mapper public interface PaymentDao { public int create(Payment payment); public Payment getPaymentById(@Param("id") Long id); }
public interface PaymentService { public int create(Payment payment); public Payment getPaymentById(@Param("id") Long id); }
@Service public class PaymentServiceImpl implements PaymentService { @Resource private PaymentDao paymentDao; public int create(Payment payment) { return paymentDao.create(payment); } public Payment getPaymentById(Long id) { return paymentDao.getPaymentById(id); } }
@RestController public class PaymentController { @Resource private PaymentService paymentService; @Value("${server.port}") private String serverPort; @PostMapping(value = "/payment/create") public CommonResult create(@RequestBody Payment payment) { int result = paymentService.create(payment); System.out.println(("*****Insert result:" + result)); if(result > 0) { return new CommonResult(200,"Insert database succeeded,serverPort: "+serverPort,result); }else{ return new CommonResult(444,"Insert database failed",null); } } @GetMapping(value = "/payment/get/{id}") public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) { Payment payment = paymentService.getPaymentById(id); if(payment != null) { return new CommonResult(200,"query was successful,serverPort: "+serverPort,payment); }else{ return new CommonResult(444,"No corresponding record,query ID: "+id,null); } } }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.cjian.springcloud.dao.PaymentDao"> <resultMap id="BaseResultMap" type="com.cjian.springcloud.bean.Payment"> <id column="id" property="id" jdbcType="BIGINT"/> <id column="serial" property="serial" jdbcType="VARCHAR"/> </resultMap> <insert id="create" parameterType="com.cjian.springcloud.bean.Payment" useGeneratedKeys="true" keyProperty="id"> insert into payment(serial) values(#{serial}); </insert> <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap"> select * from payment where id=#{id}; </select> </mapper>
Main startup class:
here
@SpringBootApplication //@EnableEurekaClient is OK without this annotation. We'll talk about it when we analyze the eureka principle public class PaymentMain001 { public static void main(String[] args) { SpringApplication.run(PaymentMain001.class, args); } }
Create table sql:
CREATE TABLE `payment`( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', `serial` varchar(200) DEFAULT '', PRIMARY KEY (id) )ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4
The other service provider will not repeat~
4. Build a consumer cloud-consumer-order80 :
@Configuration public class ApplicationContextConfig { //Add a RestTemplate to the container //RestTemplate provides a variety of convenient ways to access remote http access @Bean @LoadBalanced//Turn on the load balancing function public RestTemplate restTemplate(){ return new RestTemplate(); } }
@RestController public class OrderController { // public static final String PAYMENT_URL = "http://localhost:8001"; public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE"; @Resource private RestTemplate restTemplate; //Because the browser only supports get requests, get is used here for convenience @GetMapping("/consumer/payment/create") public CommonResult<Payment> create(Payment payment){ System.out.println("********Inserted data:" + payment); //postForObject has three parameters: request address, request parameter and returned object type return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class); } @GetMapping("/consumer/payment/get/{id}") public CommonResult<Payment> getPayment(@PathVariable("id") Long id){ System.out.println("********Inquired id: " + id); //getForObject has two parameters: request address and returned object type return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class); } }
application.yml
#When visiting a website, the default is port 80. If you give the user port 80, the user can directly access the page without port server: port: 81 spring: application: name: cloud-order-service eureka: client: register-with-eureka: true etch-registry: true service-url: #defaultZone: http://localhost:7001/eureka defaultZone: http://eureka7001.com:7001/eureka,http://eureka7001.com:7002/eureka,http://eureka7001.com:7003/eureka instance: instance-id: consumer81 prefer-ip-address: true #The access path can display the ip address #The time interval between Eureka client sending heartbeat to server, unit: seconds (default: 30 seconds) lease-renewal-interval-in-seconds: 1 #The upper limit of waiting time for Eureka server after receiving the last heartbeat, in seconds (90 seconds by default), and the timeout service is excluded lease-expiration-duration-in-seconds: 2
Main startup class:
@SpringBootApplication //@EnableDiscoveryClient public class OrderMain80 { public static void main(String[] args) { SpringApplication.run(OrderMain80.class, args); } }
Test function
Start three registries, consumers and two service providers in turn, and visit localhost:7001
visit http://localhost:81/consumer/payment/get/3
Visit again:
At the end of the foreplay, the focus of this time, the key functions of eureka and source code analysis: the length is too long. See the next article~