本文档是为了演练SpringCload的Eureka。
本文档演示EurekaServer开发、EurekaClient开发。
本文档演示EurekaClient的调度。
本文档为了更集中于SpringCloud的功能演示,没有集成MyBatis相关的功能。
本文档开发了一个SpringCloud项目,该项目中包括3个子项目:
? 1 Eureka Server项目,是注册中心,用于服务发现和调度,并实现了负载均衡功能。
? 2 订单提供者项目, 提供了订单的服务,其实就是提供了一个API,调用可以返回订单信息。
? 3 订单消费者项目, 消费订单的服务,其实就是调用 订单提供者项目 的API,该项目其实没必要注册到注册中心。
创建SpringCloud父项目
SpringCloud项目是依赖于 SpringBoot的
在idea下创建 maven 项目。项目命名为 test-springcloud?
该项目是父项目,并不提供任何功能,仅仅提供公共的依赖
修改 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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.pingbu</groupId>
<artifactId>test-springcloud</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<!-- 三个模块 -->
<modules>
<!-- 注册中心模块 -->
<module>test-springcloud-eureka-server8761</module>
<!-- 消费者模块 -->
<module>test-springcloud-consumer-order8000</module>
<!-- 提供者模块 -->
<module>test-springcloud-provider-order8001</module>
</modules>
<!-- 各依赖的版本 -->
<properties>
<spring-boot.version>2.3.12.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
<mybatis-spring-boot.version>2.1.2</mybatis-spring-boot.version>
<mysql.version>8.0.12</mysql.version>
<druid.version>1.1.21</druid.version>
<lombok.version>1.18.12</lombok.version>
<java.version>1.8</java.version>
<!-- 项目内置的两个参数,设置后编译的时候会使用这两个参数 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
该 文件加入了mybatis的依赖,其实本演示项目并没有操作数据库,这个完全可以省略。
注册中心模块,即eureka服务模块
该模块很简单,提供了注册中心的功能,即服务都注册在它上面,从而实现服务的发现。
该模块的父项目为 test-springcloud ,即上一节的项目。
该模块命名为 test-springcloud-eureka-server8761?
该模块的 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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.pingbu</groupId>
<artifactId>test-springcloud</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.pingbu</groupId>
<artifactId>test-springcloud-eureka-server8761</artifactId>
<version>1.0.0</version>
<dependencies>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<finalName>test-springcloud-eureka-server8761</finalName>
</build>
</project>
该文件引入了 eureka-server的依赖。
其实,如果考虑到高可用,应该将注册中心做成集群,本文档不考虑这个功能,后面的我会单独写这样的文章。
springboot的 application.yml 文件如下
# 端口
server:
port: 8761
spring:
application:
name: cloud-eureka-server
# Eureka配置
eureka:
instance:
# eureka服务端的实例名称
hostname: localhost
# eureka 注册中心的端口
port: 8761
server:
enable-self-preservation: false
client:
# false表示不向注册中心注册自己
register-with-eureka: false
# false表示自己端就是注册中心,职责就是维护服务实例,并不需要去检查服务
fetch-registry: false
# 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
service-url:
defaultZone: http://${eureka.instance.hostname}:${eureka.instance.port}/eureka
该模块的 Spring Main类文件如下
package com.wanshi.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
// Eureka服务端
@EnableEurekaServer
@SpringBootApplication
public class EurekaMain8761 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain8761.class, args);
}
}
该模块到这里就结束了,也没什么需要讲解的。
该模块启动后,可以在浏览器输入 http://ip:port/ 访问,访问页面如下
提供者模块,订单服务提供者
该模块命名为??test-springcloud-provider-order8001?
该模块提供了一个RESTFul的API,对!只提供了一个API,因为本文档是一个演示项目,所以,越简单越好。大家明白的,真实的项目,提供者不可能只有一个API。
这个 API 是基于RESTful的。
这个API的请求地址为:?http://ip:port/consumer/order/get/{id} ,请求方式为 get
根据地址可以看出,这就是一个普通的RESTful 接口,参数为 path参数,可接收一个 id 参数。
该api自然可以正常调用,但我们写的是SpringCloud分布式项目,因此,我们目标是通过eureka注册中心发现服务并调用。
该模块的 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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.pingbu</groupId>
<artifactId>test-springcloud</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.pingbu</groupId>
<artifactId>test-springcloud-provider-order8001</artifactId>
<version>1.0.0</version>
<dependencies>
<!-- eureka client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- spring boot -->
<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.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<finalName>test-springcloud-provider-payment8001</finalName>
</build>
</project>
可以看到,该模块引入了eureka client依赖。
该模块的 application.yml 文件如下
server:
port: 8001
spring:
application:
name: provider-order
eureka:
serverInstance:
hostname: 127.0.0.1
port: 8761
client:
# 表示将自己注册进Eureka Server默认为true
register-with-eureka: true
# 是否从Eureka Server抓去已有的注册信息,默认是true
fetch-registry: true
# 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
service-url:
defaultZone: http://${eureka.serverInstance.hostname}:${eureka.serverInstance.port}/eureka
可以看到,这个项目定义了一个 application 的 name,这个名字就是注册到 eureka server 的名字,最终也是要发现该名字。
该模块的 SpringBoot Main类文件代码如下
package com.wanshi.provider.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
// Eureka客户端
@EnableEurekaClient
@SpringBootApplication
public class ProviderOrderMain8001 {
public static void main(String[] args) {
SpringApplication.run(ProviderOrderMain8001.class, args);
}
}
注解上声明,这是一个eureka 客户端?
我们现在看看该模块提供的API,很简单的一个RestController接口,代码如下。
package com.wanshi.provider.order.controller;
import com.wanshi.provider.order.bean.Order;
import com.wanshi.provider.order.bean.ResultBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
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;
@Slf4j
@RestController
@RequestMapping("/provider/order/")
public class OrderController {
@Value("${server.port}")
private String serverPort;
@GetMapping("/get/{id}")
public ResultBean<Order> getOrderById(@PathVariable("id") Long id) {
Order result = new Order();
result.setId(1L);
result.setSerial("测试序列");
log.info("====== 查询结果:" + result);
if(result != null) {
return new ResultBean(0, "查询成功,服务端口:" + serverPort, result);
}else {
return new ResultBean(500, "查询失败");
}
}
}
不做过多的解释,该接口用到了两个自定义类,如下。
订单bean类 Order.java 如下:
package com.wanshi.provider.order.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
private Long id;
private String serial;
}
由于项目使用了 lombok ,所以,该Bean 类没有 get 和 set 方法。?
公共返回类,这个类也不多解释,代码如下:
package com.wanshi.provider.order.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultBean<T> {
private int code;
private String msg;
private T data;
public ResultBean(int _code , String _msg){
code = _code;
msg = _msg;
}
}
该模块就是这些了,没有其他的东西需要说明的。
该项目启动后,我们可以看到 eureka server中多了一个注册的项目。
消费者模块,订单消费模块
该模块调用提供者模块的API
这模块不需要注册到注册中心。
该模块的 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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.pingbu</groupId>
<artifactId>test-springcloud</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.pingbu</groupId>
<artifactId>test-springcloud-consumer-order8000</artifactId>
<version>1.0.0</version>
<dependencies>
<!-- eureka client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- spring boot -->
<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.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>
<build>
<finalName>test-springcloud-order8000</finalName>
</build>
</project>
该模块的 application.yml 文件如下:
server:
port: 8001
spring:
application:
name: provider-order
eureka:
serverInstance:
hostname: 127.0.0.1
port: 8761
client:
# 表示将自己注册进Eureka Server默认为true
register-with-eureka: true
# 是否从Eureka Server抓去已有的注册信息,默认是true
fetch-registry: true
# 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
service-url:
defaultZone: http://${eureka.serverInstance.hostname}:${eureka.serverInstance.port}/eureka
该项目的 SpringBoot Main类文件如下
package com.wanshi.provider.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
// Eureka客户端
@EnableEurekaClient
@SpringBootApplication
public class ProviderOrderMain8001 {
public static void main(String[] args) {
SpringApplication.run(ProviderOrderMain8001.class, args);
}
}
该项目的调用 提供者的 API的代码如下。
package com.wanshi.provider.order.controller;
import com.wanshi.provider.order.bean.Order;
import com.wanshi.provider.order.bean.ResultBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
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;
@Slf4j
@RestController
@RequestMapping("/provider/order/")
public class OrderController {
@Value("${server.port}")
private String serverPort;
@GetMapping("/get/{id}")
public ResultBean<Order> getOrderById(@PathVariable("id") Long id) {
Order result = new Order();
result.setId(1L);
result.setSerial("测试序列");
log.info("====== 查询结果:" + result);
if(result != null) {
return new ResultBean(0, "查询成功,服务端口:" + serverPort, result);
}else {
return new ResultBean(500, "查询失败");
}
}
}
该模块不多做解释,缺少的 Bean 可自行完善。
该项目启动后,可以在浏览器下 访问 地址? http://ip:port/consumer/order/get/1? 访问。??
返回结果如下:
|