springcloud
搭建前准备
- springboot默认的mysql版本是8.几,建立springcloud项目时父工程导入
以下依赖会出现时区问题:
<!--使用druid整合mysql数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
- 创建消费者模块的时候出现了bug,原因是子工程继承父工程的依赖
<!--使用druid整合mysql数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--阿里数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
这些依赖会去寻找数据源,但消费者不需要配置数据源,所以找不到。
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
解决:
主启动类
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
搭建微服务工程
1.建立父工程(打pom包)
pom.xml管理整个微服务工程的依赖
2.导包
注释掉有关redis的依赖,不然后面的操作可能会出错。
<!--导入springBoot依赖包 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath />
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<!--依赖管理,用于管理spring-cloud的依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<!--导入springCloudjar包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<!--引入springBoot jar包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> -->
<!--支持热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--整合redis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<!--导入pojo插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--使用druid整合mysql数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--阿里数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<!--mybatis-plus配置 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.6</version>
</dependency>
</dependencies>
2.普通maven创建子工程服务提供者和服务消费者
3.配置服务提供者和消费者的.yml文件
3.1.服务提供者:
server:
port: 8082
servlet:
context-path: /
#配置访问端口和访问的根路径
#配置数据源
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource #使用druid连接池
url: jdbc:mysql://localhost:3306/db_shop?characterEncoding=utf8
password: root
username: root
driver-class-name: com.mysql.jdbc.Driver
druid: #配置 Druid 的相关参数
# 初始化大小,最小,最大
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000 # 配置获取连接等待超时的时间
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存时间
validation-query: SELECT 1 #SELECT 1 FROM sys_user
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true # 打开 PSCache,并且指定每个连接上 PSCache 的大小
max-pool-prepared-statement-per-connection-size: 20
#filters: stat,wall,log4j # 配置监控统计拦截的 Filter,去掉后监控界面 SQL 无法统计,wall 用于防火墙
web-stat-filter: # 配置 DruidStatFilter
enabled: true
url-pattern: /*
exclusions: .js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*
stat-view-servlet: # 配置 DruidStatViewServlet
url-pattern: /druid/*
# IP 白名单,没有配置或者为空,则允许所有访问
allow: 127.0.0.1
# IP 黑名单,若白名单也存在,则优先使用
deny: 192.168.31.253
# 禁用 HTML 中 Reset All 按钮
reset-enable: false
# 登录用户名/密码
login-username: root
login-password: 123456
#视图解析配置——可配可不配
mvc:
view:
prefix: /templates/
suffix: .html
#Mybatis——plus
mybatis-plus:
type-aliases-package: edu.xlh.pojo #配置别名
mapper-locations: classpath:mappers/*.xml #指定映射文件的位置
configuration:
map-underscore-to-camel-case: false #自动开启驼峰规则映射
3.2.服务消费者:
server:
port: 8081
servlet:
context-path: /
4.服务提供者添加mysql驱动依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
5.服务提供者程序入口类
添加@SpringBootApplication
注解和@MapperScan("edu.xlh.mapper")
扫描持久层包
//主启动类
@SpringBootApplication
@MapperScan("edu.xlh.mapper")
public class SpringCloud8082provider {
public static void main(String[] args) {
SpringApplication.run(SpringCloud8082provider.class,args);
}
}
6.服务消费者程序入口类
添加@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
注解
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class SpringCloud8081consumer {
public static void main(String[] args) {
SpringApplication.run(SpringCloud8081consumer.class,args);
}
}
7.测试
7.1.配置远程调用组件:
@Configuration
public class RestTemplateConfig {
@Bean//创建对象交给spring管理
public RestTemplate getTemplate(){
return new RestTemplate();
}
}
7.2.服务提供者-8082:
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/provider/getAll")
@ResponseBody
public List<User> findAllUserInfo(){
System.out.println("----------8082服务");
return userService.findAllUsers();
}
7.3.服务消费者-8081:
@Controller
@RequestMapping("/user")
public class UserControllerConsumer {
//PROVIDER-USER代表两个服务提供者的实例
private String commonUrl="http://localhost:8082/user/";
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/consumer/find")
@ResponseBody
public List<User> findAllUsers(){
String url = commonUrl+"provider/getAll";
List list = restTemplate.getForObject(url, List.class);
return list;
}
localhost:8081/user//consumer/find
访问
8.抽取接口
8.1.建子模块
8.2.打jar包安装到本地仓库
8.3.服务提供者和消费者导入依赖
<!--引入接口-->
<dependency>
<groupId>edu.xlh</groupId>
<artifactId>springcloud-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
9.通过注册Eureka实现服务提供者集群
9.1.建子模块
9.2.导入依赖
<!--添加 eureka 注册中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
出错时可能还要加的依赖:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
9.3.配置application.yml
server:
port: 7000 #定义注册中心端口
eureka:
server:
enable-self-preservation: true #设定自我保护模式 默认值为true 不建议关闭
instance:
hostname: localhost #eureka服务的实例名称,如果有多个服务名称必须不同
client:
register-with-eureka: false #表示注册中心 不会注册自己本身
fetch-registry: false #表示自己就是注册中心,不需要检索服务
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#defaultZone: http://localhost:7000/eureka
9.4.建立一个端口为8083的服务提供者
修改从8082服务提供者copy过来的application.yml中的端口为8083:
server:
port: 8083
servlet:
context-path: /
9.5.在两个服务的提供者和一个消费者application.yml配置Eureka客户端
9.5.1.提供者:
其中instance-id: provider-user-8082
与不同端口号服务以此区别,例如8083服务提供者instance-id: provider-user-8083
#这个是配置Eureka 的客户端
application: #定义服务名称,如果是多个相同的服务,则名称必须相同
name: provider-user
eureka:
client:
service-url:
defaultZone: http://localhost:7000/eureka
instance:
instance-id: provider-user-8082 #定义微服务的名称
prefer-ip-address: true #是否显示IP和端口
配置后的yml
server:
port: 8082
servlet:
context-path: /
#配置数据源
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource #使用druid连接池
url: jdbc:mysql://localhost:3306/db_shop?characterEncoding=utf8
password: root
username: root
driver-class-name: com.mysql.jdbc.Driver
#这个是配置Eureka 的客户端
application: #定义服务名称,如果是多个相同的服务,则名称必须相同
name: provider-user
eureka:
client:
service-url:
defaultZone: http://localhost:7000/eureka
instance:
instance-id: provider-user-8082 #定义微服务的名称
prefer-ip-address: true #是否显示IP和端口
druid: #配置 Druid 的相关参数
# 初始化大小,最小,最大
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000 # 配置获取连接等待超时的时间
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存时间
validation-query: SELECT 1 #SELECT 1 FROM sys_user
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true # 打开 PSCache,并且指定每个连接上 PSCache 的大小
max-pool-prepared-statement-per-connection-size: 20
#filters: stat,wall,log4j # 配置监控统计拦截的 Filter,去掉后监控界面 SQL 无法统计,wall 用于防火墙
web-stat-filter: # 配置 DruidStatFilter
enabled: true
url-pattern: /*
exclusions: .js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*
stat-view-servlet: # 配置 DruidStatViewServlet
url-pattern: /druid/*
# IP 白名单,没有配置或者为空,则允许所有访问
allow: 127.0.0.1
# IP 黑名单,若白名单也存在,则优先使用
deny: 192.168.31.253
# 禁用 HTML 中 Reset All 按钮
reset-enable: false
# 登录用户名/密码
login-username: root
login-password: 123456
#视图解析配置
mvc:
view:
prefix: /templates/
suffix: .html
#mybatis-plus 配置
mybatis-plus:
type-aliases-package: com.ldk.pojo #配置实体别名
mapper-locations: classpath:mappers/*.xml #指定sql 映射文件的位置
configuration:
map-underscore-to-camel-case: false #自动开启驼峰规则映射
9.5.2.消费者:
server:
port: 8081
servlet:
context-path: /
eureka:
client:
register-with-eureka: false #不会将自己的信息注册到eureka中
service-url:
#链接注册中心集群
defaultZone: http://localhost:7000/eureka
9.6.在两个服务提供者和服务消费者的pom.xml中加入Eureka客户端地址依赖:
<!--添加eureka 客户端地址 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
9.7.在两个服务提供者和服务消费者的主启动类加上
@EnableEurekaClient
9.8.启动Eureka,访问localhost:7000
(可配置其他端口),再启动两个服务提供者
将服务提供者的controller的private String commonUrl="http://localhost:8082/user/";
改为
//PROVIDER-USER代表两个服务提供者的实例
private String commonUrl="http://PROVIDER-USER/user/";
9.9.在远程服务调用组件上加入负载均衡策略@LoadBalanced
@Configuration
public class RestTemplateConfig {
@Bean//创建对象交给spring管理
//开启负载均衡策略 默认是轮询策略
@LoadBalanced
public RestTemplate getTemplate(){
return new RestTemplate();
}
}
10.使用Feign简化消费者操作,实现在Eureka中的service调用服务提供者的controller,服务消费者调用Eureka中的service。
注:将消费者controller内的代码先全部注释掉
10.1.上图模块的pom.xml文件引入
<!--引入Feign支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
10.2.编写UserService接口
加上@FeignClient(value = “provider-user”)
@RequestMapping("/user/provider/getAll")
为服务提供者某方法的映射。
@FeignClient(value = "provider-user")//指定服务的名称,一定使用小写
public interface UserService {
@RequestMapping("/user/provider/getAll")
List<User> findAll();
}
10.3.服务消费者注入接口的UserService并调用接口方法
@Autowired
private UserService userService;
@GetMapping("/provider/getAll")
@ResponseBody
public List<User> findAllUserInfo(){
System.out.println("----------8082服务");
return userService.findAllUsers();
}
10.4.服务消费者的主启动类添加@EnableFeignClients
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaClient
@EnableFeignClients//开启Feign客户端服务
public class SpringCloud8081consumer {
public static void main(String[] args) {
SpringApplication.run(SpringCloud8081consumer.class,args);
}
}
11.服务的扇出=》Hystrix
定义:一个服务调用多级服务的现象。会导致调用者一直处于等待状态,用户体验不好,资源耗费严重。=>熔断机制。实现:熔断器Hystrix:能够保证当服务单元发生故障后,通过断路器机制.返回一个满足预期处理条件的数据.而不是长时间的等待或者抛出异常.这样就能避免服务长时间没有响应或者报错等影响,提升了软件的可靠性。
11.1.两个服务提供者引入依赖
<!--添加断路器配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
11.2.在8082提供者controller自定义一个因异常反馈给客户端的方法
注意方法的返回值与抛出异常方法的返回值保持一致。
//但执行请求的时候,出现故障或者访问延迟的时候
//就会来调用这个方法作为预期的数据返回给客户端
public List<User> hystrix_exception(){
List<User> list = new ArrayList<>();
User user = new User();
user.setBemail("服务不可用");
list.add(user);
return list;
}
11.3.在8082提供者controller抛出异常的方法上加 @HystrixCommand(fallbackMethod="hystrix_exception")
注解
fallbackMethod值为回调方法的方法名
@GetMapping("/provider/getAll")
@ResponseBody
@HystrixCommand(fallbackMethod="hystrix_exception")
public List<User> findAllUserInfo(){
int a = 10/0;
System.out.println("----------8082服务");
return userService.findAllUsers();
}
11.4.在8082提供者主启动类加@EnableHystrix
//主启动类
@SpringBootApplication
@MapperScan("edu.xlh.mapper")
@EnableEurekaClient
@EnableHystrix
public class SpringCloud8082provider {
public static void main(String[] args) {
SpringApplication.run(SpringCloud8082provider.class,args);
}
}
11.5.在注册中心的接口中UserService添加熔断器解决8082提供者宕机代码不跑
一般的将断路器配置到服务端,可以返回有效的数据.但是如果服务端程序宕机了.这时断路器机制将不能生效.为了让用户也能快速获取预期数据.所以将断路器配置到接口中。
11.5.1.配置依赖
pom.xml:
<!--添加断路器配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
11.5.2.建一个回调工厂类
匿名内部类中方法就是接口的方法
//用户接口回调工厂
@Component
public class UserFallBackFactory implements FallbackFactory<UserService> {
@Override
public UserService create(Throwable throwable) {
return new UserService() {
@Override
public List<User> findAll() {
List<User> list = new ArrayList<>();
User user = new User();
user.setBemail("服务不可用");
list.add(user);
return list;
}
@Override
public ResponseResult save(User user) {
return new ResponseResult(201,"服务器已经崩溃");
}
};
}
}
11.5.3.在UserService中补上fallbackFactory= UserFallBackFactory.class
@FeignClient(value = "provider-user",fallbackFactory= UserFallBackFactory.class)//指定服务的名称,一定使用小写
public interface UserService {
@RequestMapping("/user/provider/getAll")
List<User> findAll();
@RequestMapping("/user/provider/save")
ResponseResult save(User user);
}
11.5.4.消费者的.yml配置文件
feign:
hystrix:
enabled: true #启动熔断器机制 !!!!!!!!!!!!!
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 #设定断路器超时时间
配置后:
server:
port: 8081
servlet:
context-path: /
eureka:
client:
register-with-eureka: false #不会将自己的信息注册到eureka中
service-url:
#链接注册中心集群
defaultZone: http://localhost:7000/eureka
feign:
hystrix:
enabled: true #启动熔断器机制 !!!!!!!!!!!!!
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 #设定断路器超时时间
down掉8082再测试,http://localhost:8081/user/consumer/add/123/456/789
12.DashBoard仪表盘监控
监控某个时间的并发量、成功访问数量、失败访问数量、监控系统性能。目的:通过系统的监测:可以有效调用、分配服务器资源,有效解决高并发和资源合理利用。
12.1.建子模块
12.2.引入依赖
<dependencies>
<!--添加断路器配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--配置hystrix监控 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
</dependencies>
12.3.子模块.yml配置文件
server:
port: 9000 #定义注册中心端口
12.4子模块主启动类添加@EnableHystrixDashboard注解
//主启动类
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableHystrixDashboard
public class SpringCloud9000DashBoard {
public static void main(String[] args) {
SpringApplication.run(SpringCloud9000DashBoard.class,args);
}
}
12.5.访问
http://localhost:9000/hystrix
12.6. 8082提供者引入客户端依赖
<!--添加监控 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
12.7. 8082提供者配置类
@Configuration
public class DashboardConfig {
@Bean
public ServletRegistrationBean<Servlet> getServlet(){
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean<Servlet> registrationBean = new ServletRegistrationBean<>(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
}
12.8.访问
http://localhost:8082/actuator/hystrix.stream填在上图第一个框,只需修改为提供者端口号,我的为8082。
13.Eureka集群
只需复制模块,比如一共三个,只需修改.yml文件中自己的端口号,和向另外两个注册。
7000:
defaultZone: http://eureka7000.com:7001/eureka,http://eureka7002.com:7002/eureka
7001:
defaultZone: http://eureka7000.com:7000/eureka,http://eureka7002.com:7002/eureka
7002:
defaultZone: http://eureka7000.com:7000/eureka,http://eureka7002.com:7001/eureka