如何搭建一个简单的微服务工程?
1. 父工程
springcloud 工程是基于 springboot 工程的。所以我们的父工程的pom直接继承spring-boot-starter-parent,让所有的子工程也作为springboot项目。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
</parent>
然后指定spring-cloud的依赖版本统一为Finchley.RELEASE,这样子工程在引入springcloud相关包的时候就不用特意指定版本了。
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</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>
</dependencies>
</dependencyManagement>
父工程完整pom文件:
<?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.lb</groupId>
<artifactId>springcloud-simple-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>eureka</module>
<module>mirco-user</module>
<module>micro-order</module>
</modules>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2. 注册中心搭建(eureka-server)
我们选择 eureka 作为注册中心。
新建一个子工程,指定parent为刚才我们建立的父工程
<parent>
<groupId>com.lb</groupId>
<artifactId>springcloud-simple-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
Eureka 服务端启动器导入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
Eureka 服务端 完整pom文件:
<?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">
<artifactId>eureka</artifactId>
<name>eureka</name>
<version>0.0.1-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lb</groupId>
<artifactId>springcloud-simple-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
application.properties 配置文件
server.port=9001
spring.application.name=eureka-server
eureka.instance.hostname=localhost
#注册服务到eureka,这里作为服务端,不要注册到其他的eureka
eureka.client.register-with-eureka=false
#不从eureka拉取信息,客户端这里要开true,拉取服务列表
eureka.client.fetch-registry=false
#暴露的地址,不是浏览器访问的地址,是服务之间通信的地址
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka
#自我保护模式:当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。
eureka.server.enable-self-preservation=true
#Eureka-Server在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来
eureka.server.renewal-percent-threshold=0.85
#eureka server清除无效节点的间隔
#eureka.server.eviction-interval-timer-in-ms=60
启动类
@SpringBootApplication
//开启EurekaServer
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
3. 服务提供方(订单服务)
新建一个子工程 订单服务,实际上是eureka的客户端。
同样指定parent为刚才我们建立的父工程
<parent>
<groupId>com.lb</groupId>
<artifactId>springcloud-simple-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
引入eureka客户端的pom依赖,以及web包,用来与eureka-server端进行通信。
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 一定要导入这个包,因为涉及到与eureka-server端进行通信,eureka-server是默认集成了这个包的,而eureka-client没有,需要手动导入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
订单服务完整pom文件:
<?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>springcloud-simple-starter</artifactId>
<groupId>com.lb</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>micro-order</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
bootstrap.properties配置文件
#当前服务的名称
spring.application.name=micro-order
#占用端口
server.port=9012
#注册到eureka-server的地址
eureka.client.serviceUrl.defaultZone=http\://localhost\:9001/eureka/
启动类
//@EnableEurekaClient,这个配置不开也行
@SpringBootApplication
public class MicroOrderApplication {
public static void main(String[] args) {
SpringApplication.run(MicroOrderApplication.class, args);
}
}
4. 服务消费方(用户服务)
新建一个子工程 订单服务,实际上是eureka的客户端。
同样指定parent为刚才我们建立的父工程
<parent>
<groupId>com.lb</groupId>
<artifactId>springcloud-simple-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
引入eureka客户端的pom依赖,以及web包,用来与eureka-server端进行通信。
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 一定要导入这个包,因为涉及到与eureka-server端进行通信,eureka-server是默认集成了这个包的,而eureka-client没有,需要手动导入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
用户服务完整pom文件:
<?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>springcloud-simple-starter</artifactId>
<groupId>com.lb</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mirco-user</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
bootstrap.properties
#当前服务的名称
spring.application.name=micro-user
#占用端口
server.port=9011
#注册到eureka-server的地址
eureka.client.serviceUrl.defaultZone=http\://localhost\:9001/eureka/
启动类
//@EnableEurekaClient,这个配置不开也行
@SpringBootApplication
public class MicroUserApplication {
public static void main(String[] args) {
SpringApplication.run(MicroUserApplication.class, args);
}
}
5. 启动服务
先启动注册中心 eureka服务端工程, 然后启动两个eureka客户端:订单服务和用户服务,看看这两个服务是否都注册到注册中心了。
当订单服务和用户服务 启动注册成功时, 会发现eureka服务端 会有 注册服务实例成功的日志。
查看eureka的 监控页面 http://127.0.0.1:9001/ ,可以看到 服务列表里已经 有 订单服务和用户服务了。
6. 服务间调用
当订单服务 和 用户服务都成功注册 到 注册中心之后,那么 这两个服务 都会定时的从注册中心拉取服务列表, 用于调用。
我们让 订单服务 作为服务提供者,让用户服务调用,测试一下能否调用成功。
1. 订单服务提供接口
模拟 返回某个用户的订单信息
@RequestMapping("/order")
@RestController
public class OrderController {
@GetMapping("/list")
public String getOrderList(String username){
return "这是用户 :" + username +" 所有的订单信息";
}
}
2. 用户服务调用订单服务提供的接口
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
private RestTemplate restTemplate;
@Bean
@LoadBalanced // 如果通过服务名访问要加这个注解,用于负载均衡该服务名下的所有服务实例,如果是ip+端口访问就不要加这个注解
public RestTemplate restTemplate() {
return new RestTemplate();
}
@GetMapping("/orderList")
public String getOrderList(String username) {
// 根据服务名调用 订单服务的 /order/list接口,并传入参数
return restTemplate.getForObject("http://" + "micro-order" + "/order/list?username=" + username, String.class);
}
}
浏览器 调用 用户服务的 /user/orderList接口:
可以看到已经成功通过用户服务的/user/ordeeList接口 调用到了订单服务的/order/list 接口。