前言
近段时间自己学习了下SpringCloud相关技术,由于Springcloud是一个完整的分布式微服务框架,所包含的技术很多。本文主要介绍SpringCloud环境搭建和各种服务注册中心的使用,以及差异优缺点,仅作为笔记,方便自己以后的复习
版本选择
SpringCloud版本依赖于SpringBoot的版本,可以从官网查询相关版本依赖关系:spring.io/projects/sp…
springboot 2.2.5.RELEASE
springcloud Hoxton.SR3
搭建一个SpringCloud项目
pom依赖
<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>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties>
<dependencyManagement>
<dependencies>
<!--springboot版本-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springcloud版本-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springcloud-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>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!--mybatis-springboot-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!--druid-spring-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
</dependencies>
</dependencyManagement>
<!--springboot maven打包插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
服务注册中心
Eureka
Eureka是netflix推出的一款服务注册中心,它是C/S架构的。目前2.0版本已经从github上停更,详细可见 github.com/Netflix/eur…
搭建Eureka Server
项目中创建对应的module
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
修改application.yml配置文件
server:
port: 7001
#eureka相关配置
eureka:
instance:
hostname: eureka7001.com #本地配置host文件
client:
#是否向Eureka中注册。因为本模块是Eureka Server端,不需要注册自己,默认是true
register-with-eureka: false
#是否从Eureka检索服务,当前是Server端不需要检索,默认是true
fetch-registry: false
service-url:
# 单机版
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
# 集群版 互相守望
# defaultZone: http://eureka7002.com:7002/eureka
server:
# 禁用eureka的自我保护机制
# enable-self-preservation: false
# 服务维持心跳时间,单位ms
# expected-client-renewal-interval-seconds: 2000
修改主启动类
@SpringBootApplication
@EnableEurekaServer #启用Eureka Server
public class EurekaServer7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer7001.class, args);
}
}
测试访问
访问 http://eureka服务器ip:端口
服务提供者
项目中创建对应的module
#端口号配置
server:
port: 8001
#spring相关配置
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf8&useSSL=false
username: root
password: 123456
#mybatis相关配置
mybatis:
mapper-locations:
- classpath:mapper/*.xml
type-aliases-package: com.sun.cloud.pojo
configuration:
map-underscore-to-camel-case: true
#mybatis日志打印
logging.level.com.sun.cloud.mapper: debug
#eureka Client相关配置
eureka:
instance:
# eureka web端显示主机名称
instance-id: payment8001
# 显示ip地址
prefer-ip-address: true
# eureka向客户端发送心跳的时间,单位:s(默认是30s)
# lease-renewal-interval-in-seconds: 1
# eureka服务端在最后一次心跳后的等待时间上限,单位:s(默认是90s),超时将删除服务
# lease-expiration-duration-in-seconds: 2
client:
register-with-eureka: true
fetch-registry: true
service-url:
# 集群版
# defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
# 单机版
defaultZone: http://localhost:7001/eureka
主启动类
@SpringBootApplication
@EnableEurekaClient //启用eureka client
@EnableDiscoveryClient #启用发现服务客户端
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class, args);
}
}
服务消费者
项目中创建对应的module
<dependencies>
<!--eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--javabean对象包-->
<dependency>
<groupId>com.sun</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
application.yml配置文件
server:
port: 80
spring:
application:
name: cloud-consumer-order
#eureka相关配置
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
# defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
defaultZone: http://localhost:7001/eureka #单机版
主启动类
@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
}
自动配置类
@Configuration
public class ApplicationConfig {
@Bean
@LoadBalanced // 不添加该注解,在多个服务的时候,出现在报错
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
控制层
@RestController
@Slf4j
@RequestMapping("/consumer/payment")
public class OrderController {
// private static final String PAYMENT_URL = "http://localhost:8001";
// 服务提供者的服务名
private static final String APPLICATION_NAME = "http://CLOUD-PAYMENT-SERVICE";
@Autowired
RestTemplate restTemplate;
@GetMapping("/get/{id}")
public CommonResult get(@PathVariable("id") Integer id) {
log.info("消费端查询订单");
return restTemplate.getForObject(APPLICATION_NAME + "/payment/get/" + id, CommonResult.class);
}
}
Zookeeper
前提准备
centos服务器上安装配置好zookeeper
服务提供者
项目中创建对应的module
<dependencies>
<!--zookeeper依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<exclusions>
<!--先排除自带的zookeeper-3.5.3-beta,如果zookeeper不是对应版本,则会提示相关报错-->
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--引入我们按照的zookeeper对应的版本-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
修改application.yml配置文件
server:
port: 8004 #端口自定义
spring:
application:
name: cloud-payment-service #服务名自定义
cloud:
zookeeper:
# zookeeper配置
connect-string: 192.168.126.100:2181 #zookeeper的服务器ip:端口
修改主启动类
@SpringBootApplication
@EnableDiscoveryClient #zookeeper和consul作为注册中心的时候使用该注解
public class PaymentMain8004 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8004.class, args);
}
}
检查zookeeper
发现服务已经注册到zookeeper下,且该服务是临时节点,当服务宕机之后,zookeeper会删除该节点
[zk: localhost:2181(CONNECTED) 4] ls /services/cloud-payment-service
[68849763-dd0a-4b5d-b49c-d038fc25f85e]
服务消费者
项目中创建对应的module
依赖和服务提供者相同
修改application.yml配置文件
server:
port: 80
spring:
application:
name: cloud-consumer-zk-order
cloud:
zookeeper:
connect-string: 192.168.126.100:2181
修改主启动类
@SpringBootApplication
@EnableDiscoveryClient
public class OrderZKMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderZKMain80.class, args);
}
}
消费服务
@RestController
@RequestMapping("/consumer/payment")
public class OrderController {
// 消费提供者注册进zookeeper的服务名
private static final String APPLICATION_NAME = "http://cloud-payment-service";
@Autowired
RestTemplate restTemplate;
@GetMapping("/zk")
public String zk() {
return restTemplate.getForObject(APPLICATION_NAME + "/payment/zk", String.class);
}
}
Consul
安装
#解压
unzip consul_1.7.2_linux_amd64.zip
#解压后的文件只有一个consul可执行文件
#移动到/usr/local/bin/目录下
mv consul /usr/local/bin/
#执行consul,指定ip运行
consul agent -dev -client 192.168.126.100
#访问地址
http://192.168.126.100:8500
服务提供者
项目中创建对应的module
<dependencies>
<!--consul依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--javabean对象包-->
<dependency>
<groupId>com.sun</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
修改application.yml配置文件
server:
port: 8006
spring:
application:
name: cloud-payment-service
cloud:
consul:
host: localhost #consul的ip地址
port: 8500 #consul的端口
discovery:
service-name: ${spring.application.name} #注册进consul的服务名
heartbeat:
health-check-critical-timeout: 10s #过多少秒健康检查不通过,从consul中删除该服务
主启动类
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8006 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8006.class, args);
}
}
服务消费者
依赖同服务提供者
修改application.yml配置文件
server:
port: 80
spring:
application:
name: cloud-consumer-consul-order
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
主启动类
同服务提供者相同
三个注册中心的异同点
| 组件名 | 语言 | CAP | 服务健康检查 | 对外暴露的接口 |
|---|---|---|---|---|
| eureka | java | AP | 可配支持 | HTTP |
| zookeeper | java | CP | 支持 | 客户端 |
| consule | go | CP | 支持 | HTTP、 DNS |