标签:服务 Spring org springframework eureka user import java Cloud
Spring Cloud
(注:本文为学习黑马课程所做笔记,文后有过程中所遇的问题与相关解决方案。)
一,简介
1.系统结构演变
集中式架构 --> 垂直拆分 --> 分布式服务 --> 面向服务架构(SOA)–> 微服务架构
1.1 集中式架构
将所有功能都部署在一起,以减少部署节点和成本
优点:系统开发速度快,维护成本低,适用于并发要求较低的系统
缺点:代码耦合度高,后期维护困难,无法针对不同模块进行针对性优化,无法水平扩展,单点容错率低,并发能力差
1.2 垂直拆分
当访问量逐渐增大,单一应用无法满足需求,此时为了应对更高的并发和业务需求,我们根据业务功能对系统进行拆分:
优点:系统拆分实现了流量分担,解决了并发问题,可以针对不同模块进行优化,方便水平扩展,负载均衡,容错率提高
缺点:系统间相互独立,会有很多重复开发工作,影响开发效率
1.3 分布式服务
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。
优点:将基础服务进行了抽取,系统间相互调用,提高了代码复用和开发效率
缺点:系统间耦合度变高,调用关系错综复杂,难以维护
1.4 面向服务架构(SOA)
SOA(Service Oriented Architecture)面向服务的架构:它是一种设计方法,其中包含多个服务, 服务之间通过相
互依赖最终提供一系列的功能。一个服务 通常以独立的形式存在与操作系统进程中。各个服务之间 通过网络调用。
SOA缺点:每个供应商提供的ESB产品有偏差,自身实现较为复杂;应用服务粒度较大,ESB集成整合所有服务和协议、数据转换使得运维、测试部署困难。所有服务都通过一个通路通信,直接降低了通信速度。
1.5 微服务架构
微服务架构是使用一套小服务来开发单个应用的方式或途径,每个服务基于单一业务能力构建,运行在自己的进程中,并使用轻量级机制通信,通常是HTTP API,并能够通过自动化部署机制来独立部署。这些服务可以使用不同的编程语言实现,以及不同数据存储技术,并保持最低限度的集中式管理。
微服务的特点:
单一职责:微服务中每一个服务都对应唯一的业务能力,做到单一职责
微:微服务的服务拆分粒度很小,例如一个用户管理就可以作为一个服务。每个服务虽小,但“五脏俱全”。
面向服务:面向服务是说每个服务都要对外暴露Rest风格服务接口API。并不关心服务的技术实现,做到与平台
和语言无关,也不限定用什么技术实现,只要提供Rest的接口即可。
自治:自治是说服务间互相独立,互不干扰
团队独立:每个服务都是一个独立的开发团队,人数不能过多。
技术独立:因为是面向服务,提供Rest接口,使用什么技术没有别人干涉
前后端分离:采用前后端分离开发,提供统一Rest接口,后端不用再为PC、移动端开发不同接口
数据库分离:每个服务都使用自己的数据源
部署独立,服务间虽然有调用,但要做到服务重启不影响其它服务。有利于持续集成和持续交付。每个服务都是独立的组件,可复用,可替换,降低耦合,易维护
2.服务调用方式
无论是微服务还是SOA,都面临着服务间的远程调用。
常见的远程调用方式有以下2种:
- RPC:Remote Produce Call远程过程调用,RPC基于Socket,工作在会话层。自定义数据格式,速度快,效率高。早期的webservice,现在热门的dubbo,都是RPC的典型代表
- Http:http其实是一种网络传输协议,基于TCP,工作在应用层,规定了数据传输的格式。现在客户端浏览器与服务端通信基本都是采用Http协议,也可以用来进行远程服务调用。缺点是消息封装臃肿,优势是对服务的提供和调用方没有任何技术限定,自由灵活,更符合微服务理念。
RPC:基于socket,速度快,效率高;webservice,dubbo
HTTP:基于TCP,封装比较臃肿;对服务和调用方没有任何技术,语言的限定,自由灵活;RESTful,Spring Cloud
二,Spring Cloud
1. 简介
Spring最擅长的就是集成,把世界上最好的框架拿过来,集成到自己的项目中。
Spring Cloud也是一样,它将现在非常流行的一些技术整合到一起,实现了诸如:配置管理,服务发现,智能路由,
负载均衡,熔断器,控制总线,集群状态等功能;协调分布式环境中各个系统,为各类服务提供模板性配置。其主要
涉及的组件包括:
- Eureka:注册中心
- Zuul、Gateway:服务网关
- Ribbon:负载均衡
- Feign:服务调用
- Hystrix或Resilience4j:熔断器
2. 创建微服务工程
创建微服务工程heima-springcloud,用户服务工程user-service,服务消费工程consumer-demo
需求:查询数据库中的用户数据并输出到浏览器
- 父工程heima-springcloud:添加spring boot父坐标和管理其他组件的依赖
- 用户服务工程user-service:整合mybatis查询数据库中用户数据;提供查询用户服务
- 服务消费工程consumer-demo:利用查询用户服务获取用户数据输出到浏览器
2.1 搭建工程
- 创建微服务父工程heima-springcloud
- 创建微服务子工程user-service
- 创建微服务子工程consumer-demo
- 给父工程heima-springcloud添加依赖
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.xmx</groupId>
<artifactId>heima-springcloud</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>user-service</module>
<module>consumer-demo</module>
</modules>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<mapper.starter.version>2.1.5</mapper.starter.version>
<mysql.version>5.1.46</mysql.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<!--通过scope的import可以继承spring-cloud-dependencies工程中的依赖-->
<scope>import</scope>
</dependency>
<!-- 通用Mapper启动器 -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>${mapper.starter.version}</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2 搭建配置user-service工程
配置user-service工程能够根据用户id查询数据库中用户
需求:可以访问http://localhost:9091/user/8输出用户数据
实现步骤:
- 添加启动依赖(web,通用Mapper)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 通用Mapper启动器 -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
- 创建启动引导类和配置文件
引导类
package com.xmx.user;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;
@SpringBootApplication
@MapperScan("com.xmx.user.mapper")
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
配置文件:
server:
port: 9091
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springcloud
username: root
password: root
mybatis:
type-aliases-package: com.xmx.user.pojo
- 修改配置文件中的参数
- 编写测试代码(UserMapper,UserService,UserController)
User
package com.xmx.user.pojo;
import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
/**
* @Author Xumx
* @Date 2021/4/7 21:47
* @Version 1.0
*/
@Data
@Table(name = "tb_user")
public class User {
//id
@Id
//开启主键自动回填
@KeySql(useGeneratedKeys = true)
private Long id;
//用户名
private String userName;
private String password;
private String name;
private Integer age;
private Integer sex;
private Date birthday;
private Date created;
private Date updated;
private String note;
}
UserMapper
package com.xmx.user.mapper;
import com.xmx.user.pojo.User;
import tk.mybatis.mapper.common.Mapper;
/**
* @Author Xumx
* @Date 2021/4/9 15:37
* @Version 1.0
*/
public interface UserMapper extends Mapper<User> {
}
UserService:
package com.xmx.user.service;
import com.xmx.user.mapper.UserMapper;
import com.xmx.user.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @Author Xumx
* @Date 2021/4/9 15:38
* @Version 1.0
*/
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
/*
* 根据主键查询用户
* */
public User queryById(Long id){
return userMapper.selectByPrimaryKey(id);
}
}
UserController
package com.xmx.user.controller;
import com.xmx.user.pojo.User;
import com.xmx.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
* @Author Xumx
* @Date 2021/4/9 15:59
* @Version 1.0
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User queryById(@PathVariable Long id){
return userService.queryById(id);
}
}
- 测试
创建数据库springcloud:
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_name` varchar(100) DEFAULT NULL COMMENT '用户名',
`password` varchar(100) DEFAULT NULL COMMENT '密码',
`name` varchar(100) DEFAULT NULL COMMENT '姓名',
`age` int(10) DEFAULT NULL COMMENT '年龄',
`sex` tinyint(1) DEFAULT NULL COMMENT '性别,1男性,2女性',
`birthday` date DEFAULT NULL COMMENT '出生日期',
`note` varchar(255) DEFAULT NULL COMMENT '备注',
`created` datetime DEFAULT NULL COMMENT '创建时间',
`updated` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`user_name`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES ('1', 'zhangsan', '123456', '张三', '30', '1', '1964-08-08', '张三同学在学Java', '2014-09-19 16:56:04', '2014-09-21 11:24:59');
INSERT INTO `tb_user` VALUES ('2', 'lisi', '123456', '李四', '21', '2', '1995-01-01', '李四同学在传智学Java', '2014-09-19 16:56:04', '2014-09-19 16:56:04');
INSERT INTO `tb_user` VALUES ('3', 'wangwu', '123456', '王五', '22', '2', '1994-01-01', '王五同学在学php', '2014-09-19 16:56:04', '2014-09-19 16:56:04');
INSERT INTO `tb_user` VALUES ('4', 'zhangliu', '123456', '张六', '20', '1', '1996-09-01', '张六同学在传智播客学Java', '2014-09-19 16:56:04', '2014-09-19 16:56:04');
INSERT INTO `tb_user` VALUES ('5', 'lina', '123456', '李娜', '28', '1', '1988-01-01', '李娜同学在传智播客学Java', '2014-09-19 16:56:04', '2014-09-19 16:56:04');
INSERT INTO `tb_user` VALUES ('6', 'lilei', '123456', '李雷', '23', '1', '1993-08-08', '李雷同学在传智播客学Java', '2014-09-20 11:41:15', '2014-09-20 11:41:15');
INSERT INTO `tb_user` VALUES ('7', 'hanmeimei', '123456', '韩梅梅', '24', '2', '1992-08-08', '韩梅梅同学在传智播客学php', '2014-09-20 11:41:15', '2014-09-20 11:41:15');
INSERT INTO `tb_user` VALUES ('8', 'itcast', '123456', '传智播客', '21', '2', '2008-07-08', '传智播客搞IT教育', '2014-09-20 11:41:15', '2014-09-20 11:41:15');
INSERT INTO `tb_user` VALUES ('9', 'heima', '123456', '黑马', '18', '2', '2012-08-08', '黑马是传智播客高端品牌', '2014-09-20 11:41:15', '2014-09-20 11:41:15');
INSERT INTO `tb_user` VALUES ('10', 'linus', '123456', '林纳斯', '45', '2', '1971-08-08', '林纳斯搞了linux又搞git', '2014-09-20 11:41:15', '2014-09-20 11:41:15');
INSERT INTO `tb_user` VALUES ('11', 'leijun', '123456', '雷布斯', '33', '2', '1983-08-08', '小爱同学;are you ok', '2014-09-20 11:41:15', '2014-09-20 11:41:15');
INSERT INTO `tb_user` VALUES ('12', 'madaye', '123456', '马大爷', '46', '2', '1980-08-08', '马大爷花呗可以不还吗', '2014-09-20 11:41:15', '2014-09-20 11:41:15');
运行引导类,输入网址:http://localhost:9091/user/8
结果如下:
2.3 搭建配置consumer-demo工程
目的:编写测试类使用restTemplate访问user-service的路径根据id查询用户
需求:访问http://localhost:8080/consumer/8 使用RestTemplate获取http://localhost:9091/user/8 的数据
实现步骤:
- 添加启动器依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
- 创建启动引导类(注册RestTemplate)和配置文件
package com.xmx.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- 编写测试代码(ConsumerController中使用RestTemplate访问服务获取数据)
User
package com.xmx.consumer.pojo;
import lombok.Data;
import java.util.Date;
/**
* @Author Xumx
* @Date 2021/4/7 21:47
* @Version 1.0
*/
@Data
public class User {
//id
private Long id;
//用户名
private String userName;
private String password;
private String name;
private Integer age;
private Integer sex;
private Date birthday;
private Date created;
private Date updated;
private String note;
}
ConsumerController
package com.xmx.consumer.controller;
import com.xmx.consumer.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @Author Xumx
* @Date 2021/4/9 16:27
* @Version 1.0
*/
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/{id}")
public User queryById(Long id){
String url = "http://localhost:9091/user/8";
User user = restTemplate.getForObject(url, User.class);
return user;
}
}
- 测试
同事启动两个引导类,输入 http://localhost:8080/consumer/8
结果如下:
3. Eureka注册中心
原理图:
Eureka的主要功能是进行服务管理,定期检查服务状态,返回服务地址列表。
3.1 搭建eureka-server工程
添加eureka对应依赖和编写引导类搭建eureka服务并可访问eureka服务界面
Eureka是服务注册中心,只做服务注册;自身并不提供服务也不消费服务。可以搭建web工程使用Eureka,可以使用Spring Boot方式搭建。
搭建步骤:
- 创建工程eureka-server
- 添加启动器依赖
<dependencies>
<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>
</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>
</dependencies>
- 编写启动引导类(添加Eureka的服务注解)和配置文件
EurekaServerApplication
package com.xmx;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
//声明当前应用是Eureka服务
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
- 修改配置文件(端口,应用名称)
application.yml
server:
port: 10086
spring:
application:
name: eureka-server
eureka:
client:
service-url:
# eureka服务地址,如果是集群的话,需要指定其它集群eureka地址
defaultZone: http://127.0.0.1:10086/eureka
# 不注册自己
register-with-eureka: false
# 不拉取服务
fetch-registry: false
- 启动测试
启动引导类,输入网址:http://localhost:10086/
结果如下:
3.2 服务注册与发现
目标:将user-service的服务注册到eureka并在consumer-demo中可以根据服务名称调用
服务注册:在服务提供工程user-service上添加Eureka客户端依赖;自动将服务注册到EurekaService服务地址列表。
- 添加依赖,在user-service中添加Eureka客户端依赖:
<!-- Eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 改造启动引导类;添加开启Eureka客户端发现的注解;
在启动类上开启Eureka客户端功能,通过添加 @EnableDiscoveryClient 来开启Eureka客户端功能
@SpringBootApplication
@MapperScan("com.xmx.user.mapper")
@EnableDiscoveryClient // 开启Eureka客户端发现功能
public class UserServiceDemoApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceDemoApplication.class, args);
}
}
- 修改配置文件;设置Eureka服务地址
编写user-service\src\main\resources\application.yml配置文件为如下
server:
port: 9091
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springcloud
username: root
password: root
application:
#应用名
name: user-service
mybatis:
type-aliases-package: cn.itcast.user.pojo
eureka:
client:
service-url:
defaultZone: http://localhost:10086/eureka
服务发现:在服务消费工程consumer-demo上添加Eureka客户端依赖;可以使用工具类根据服务名称获取对应的服务地址列表。
- 添加依赖,在consumer-demo\pom.xml 添加如下依赖
<!-- Eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 添加开启Eureka客户端发现的注解;
在启动类上开启Eureka客户端功能,通过添加 @EnableDiscoveryClient 来开启Eureka客户端功能
package com.xmx.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient //开启Eureka客户端发现功能
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- 修改配置文件;设置Eureka服务地址
spring:
application:
name: consumer-demo
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
- 改造处理器类ConsumerController,可以使用工具类DiscoveryClient根据服务名称获取对应服务地址列表。
package com.xmx.consumer.controller;
import com.xmx.consumer.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
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;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* @Author Xumx
* @Date 2021/4/9 16:27
* @Version 1.0
*/
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/{id}")
public User queryById(@PathVariable Long id){
String url = "http://localhost:9091/user/"+id;
//获取eureka中注册的user-service的实例
List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
ServiceInstance serviceInstance = instances.get(0);
url = "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/user/"+id;
User user = restTemplate.getForObject(url, User.class);
return user;
}
}
3.3 Eureka Server高可用配置
目标:可以启动两台eureka-server实例
Eureka Server是一个web应用,可以启动多个实例(配置不同端口)保证Eureka Server的高可用
高可用配置:将Eureka server作为一个服务注册到其它Eureka Server,这样多个Eureka Server之间就能够互相发现对方,同步服务,实现Eureka Server集群。
我们假设要搭建两台EurekaServer的集群,端口分别为:10086和10087
修改原来的EurekaServer配置;修改 eureka-server\src\main\resources\application.yml 如下:
server:
port: ${port:10086}
spring:
application:
# 应用名称,会在eureka中作为服务的id(serviceId)
name: eureka-server
eureka:
client:
service-url:
# eureka服务地址;如果是集群则是其它服务器地址,后面要加/eureka
defaultZone: ${defaultZone:http://127.0.0.1:10086/eureka}
# 是否注册自己,自身不提供服务所以不注册
#register-with-eureka: false
# 是否拉取服务
#fetch-registry: false
所谓的高可用注册中心,其实就是把EurekaServer自己也作为一个服务,注册到其它EurekaServer上,这样多个
EurekaServer之间就能互相发现对方,从而形成集群。
3.4 Eureka客户端与服务端配置
目标:配置eureka客户端user-service的注册,续约等配置项,配置eureka客户端consumer-demo的获取服务间隔时间;了解失效剔除和自我保护。
Eureka客户端工程
1. user-service服务提供
服务地址使用ip的方式
续约
2. consumer-demo服务消费
获取服务地址的频率
Eureka服务端工程eureka-server
失效剔除
自我保护
3.4.1 服务注册
默认注册时使用的是主机名或者localhost,如果想用ip进行注册,可以在 user-service 中添加配置如下:
eureka:
instance:
ip-address: 127.0.0.1 # ip地址
prefer-ip-address: true # 更倾向于使用ip,而不是host名
3.4.2 服务续约
在注册服务完成以后,服务提供者会维持一个心跳(定时向EurekaServer发起Rest请求),告诉EurekaServer:“我还活着”。这个我们称为服务的续约(renew);
有两个重要参数可以修改服务续约的行为;可以在 user-service 中添加如下配置项:
eureka:
instance:
#服务续约(renew)的间隔,默认30秒
lease-renewal-interval-in-seconds: 5
#服务失效时间,默认90秒
lease-expiration-duration-in-seconds: 5
也就是说,默认情况下每隔30秒服务会向注册中心发送一次心跳,证明自己还活着。如果超过90秒没有发送心跳,EurekaServer就会认为该服务宕机,会定时(eureka.server.eviction-interval-timer-in-ms设定的时间)从服务列表中移除,这两个值在生产环境不要修改,默认即可。
3.4.3 获取服务列表
当服务消费者启动时,会检测 eureka.client.fetch-registry=true 参数的值,如果为true,则会从Eureka Server服务的列表拉取只读备份,然后缓存在本地。并且 每隔30秒 会重新拉取并更新数据。可以在 consumer-demo 项目中通过下面的参数来修改:
eureka:
client:
registry-fetch-interval-seconds: 30
3.4.4 失效剔除和自我保护
eureka:
server:
enable-self-preservation: false # 关闭自我保护模式(缺省为打开)
3.5 负载均衡Ribbon简介及其应用
目标:描述负载均衡和ribbon的作用
负载均衡是一个算法,可以通过该算法实现从地址列表中获取一个地址进行服务调用。
在Spring Cloud中提供了负载均衡器:Ribbon。Ribbon提供了轮询,随机两种负载均衡算法(默认是轮询)可以实现从地址列表中使用负载均衡算法获取地址进行服务调用。
目标:配置启动两个用户服务,在consumer-demo中使用服务名实现根据用户id获取用户
需求:可以使用RestTemplate访问http://user-service/user/8 获取服务数据。
可以使用Ribbon负载均衡:在执行RestTemplate发送服务地址请求的时候,使用负载均衡拦截器拦截,根据服务名获取服务地址列表,使用Ribbon负载均衡算法从服务地址列表中选择一个服务地址,访问该地址获取服务数据。
实现步骤:
- 启动多个user-service实例(9091,9092)
- 修改RestTemplate实例化方法,添加负载均衡注解
因为Eureka中已经集成了Ribbon,所以我们无需引入新的依赖。
直接修改 consumer-demo\src\main\java\com\xmx\consumer\ConsumerApplication.java
在RestTemplate的配置方法上添加 @LoadBalanced 注解:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
- 修改ConsumerController
修改 consumer-demo\src\main\java\com\xmx\consumer\controller\ConsumerController.java 调用方式,不再手动获取ip和端口,而是直接通过服务名称调用;
@GetMapping("{id}")
public User queryById(@PathVariable("id") Long id){
String url = "http://user-service/user/" + id;
User user = restTemplate.getForObject(url, User.class);
return user;
}
- 测试
在实例化RestTemplate的时候使用@LoadBalanced,服务地址直接可以使用服务名。
了解:Ribbon默认的负载均衡策略是轮询。SpringBoot也帮提供了修改负载均衡规则的配置入口在consumerdemo的配置文件中添加如下,就变成随机的了:
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
格式是: {服务名称}.ribbon.NFLoadBalancerRuleClassName
上述代码上传至码云:springcloud 中的master分支
3.6 熔断器Hystrix简介
Hystrix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。
微服务中,服务间调用关系错综复杂,一个请求,可能需要调用多个微服务接口才能实现,会形成非常复杂的调用链路,如果此时,某个服务出现异常,请求阻塞,用户请求就不会得到响应,则tomcat的这个线程不会释放,于是越来越多的用户请求到来,越来越多的线程会阻塞,服务器支持的线程和并发数有限,请求一直阻塞,会导致服务器资源耗尽,从而导致所有其它服务都不可用,形成雪崩效应。
这就好比,一个汽车生产线,生产不同的汽车,需要使用不同的零件,如果某个零件因为种种原因无法使用,那么就会造成整台车无法装配,陷入等待零件的状态,直到零件到位,才能继续组装。 此时如果有很多个车型都需要这个零件,那么整个工厂都将陷入等待的状态,导致所有生产都陷入瘫痪。一个零件的波及范围不断扩大。
Hystrix解决雪崩问题的手段主要是服务降级,包括:线程隔离,服务熔断
3.7 线程隔离&服务降级
Hystrix解决雪崩效应:线程隔离,服务熔断
线程隔离:用户请求不直接访问服务,而是使用线程池中空闲的线程访问服务,加速失败判断时间
服务降级:及时返回服务调用失败的结果,让线程不因为等待服务而阻塞。
3.8 服务熔断
在服务熔断中,使用的熔断器,也叫断路器,其英文单词为:Circuit Breaker
熔断机制与家里使用的电路熔断原理类似;当如果电路发生短路的时候能立刻熔断电路,避免发生灾难。在分布式系统中应用服务熔断后;服务调用方可以自己进行判断哪些服务反应慢或存在大量超时,可以针对这些服务进行主动熔断,防止整个系统被拖垮。
Hystrix的服务熔断机制,可以实现弹性容错;当服务请求情况好转之后,可以自动重连。通过断路的方式,将后续请求直接拒绝,一段时间(默认5秒)之后允许部分请求通过,如果调用成功则回到断路器关闭状态,否则继续打开,拒绝请求的服务。
Hystrix的熔断状态机模型:
上述代码已上传至码云:springcloud 中的hystrixdemo分支
三,Feign
1. Feign简介
Feign也叫伪装:
Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样。你不用再自己拼接url,拼接参数等等操作,一切都交给Feign去做。
2. Feign作用
Feign主要作用:自动根据参数拼接http请求地址
目标:Feign的作用;使用Feign实现consumer-demo代码中调用服务
分析:
- 导入启动器依赖
<!--Feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 开启Feign功能
在 ConsumerApplication 启动类上,添加注解,开启Feign功能(在 ConsumerApplication 启动类上,添加注解,开启Feign功能)
@SpringCloudApplication //可以代替上面三个
@EnableFeignClients //开启Feign功能
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- 编写Feign客户端
在 consumer-demo 中编写如下Feign客户端接口类:
package com.xmx.consumer.client;
import com.xmx.consumer.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* @Author Xumx
* @Date 2021/4/10 17:42
* @Version 1.0
*/
@FeignClient("user-service") //声明当前类是一个Feign客户端,指定服务名为user-service
public interface UserClient {
//http://user-service/user/123
@GetMapping("/user/{id}")
User queryById(@PathVariable Long id);
}
- 编写一个处理器ConsumerFeignController,注入Feign客户端并使用;
package com.xmx.consumer.controller;
import com.xmx.consumer.client.UserClient;
import com.xmx.consumer.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
* @Author Xumx
* @Date 2021/4/10 17:46
* @Version 1.0
*/
@RestController
@RequestMapping("/cf")
public class ConsumerFeignController {
@Autowired
private UserClient userClient;
@GetMapping("/{id}")
public User queryById(@PathVariable Long id){
return userClient.queryById(id);
}
}
- 测试
3. Feign负载均衡及熔断
目标:可以配置Feign内置ribbon配置项和Hystrix熔断的Fallback配置
- 负载均衡
- 服务熔断
- 请求压缩
- 日志级别
都可以通过配置项在Feign中开启使用。
3.1 负载均衡
因为ribbon内部有重试机制,一旦超时,会自动重新发起请求。如果不希望重试,可以添加配置:
修改 consumer-demo\src\main\resources\application.yml 添加如下配置:
ribbon:
ConnectTimeout: 1000 # 连接超时时长
ReadTimeout: 2000 # 数据通信超时时长
MaxAutoRetries: 0 # 当前服务器的重试次数
MaxAutoRetriesNextServer: 0 # 重试多少次服务
OkToRetryOnAllOperations: false # 是否对所有的请求方式都重试
3.2 服务熔断
修改 consumer-demo\src\main\resources\application.yml 添加如下配置:
feign:
hystrix:
enabled: true # 开启Feign的熔断功能
首先,要定义一个类,实现刚才编写的UserFeignClient,作为fallback的处理类
package com.xmx.consumer.client.fallback;
import com.xmx.consumer.client.UserClient;
import com.xmx.consumer.pojo.User;
import org.springframework.stereotype.Component;
/**
* @Author Xumx
* @Date 2021/4/10 19:07
* @Version 1.0
*/
@Component
public class UserClientFallback implements UserClient {
@Override
public User queryById(Long id) {
User user = new User();
user.setId(id);
user.setName("用户异常");
return user;
}
}
然后在UserFeignClient中,指定刚才编写的实现类
@FeignClient(value = "user-service",fallback = UserClientFallback.class,configuration = FeignConfig.class)
public interface UserClient {
//http://user-service/user/123
@GetMapping("/user/{id}")
User queryById(@PathVariable Long id);
}
3.2 请求压缩
Spring Cloud Feign 支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。通过下面的参数即可开启请求与响应的压缩功能也可以对请求的数据类型,以及触发压缩的大小下限进行设置:
feign:
hystrix:
enabled: true # 开启Feign的熔断功能
compression:
request:
enabled: true # 开启请求压缩
mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
min-request-size: 2048 # 设置触发压缩的大小下限
response:
enabled: true
3.2 日志级别
在 consumer-demo 的配置文件中设置com.itheima包下的日志级别都为 debug
修改 consumer-demo\src\main\resources\application.yml 添加如下配置:
logging:
level:
com.itheima: debug
在 consumer-demo 编写FeignConfig配置类,定义日志级别
package com.xmx.consumer.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author Xumx
* @Date 2021/4/10 19:16
* @Version 1.0
*/
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel(){
//记录所有请求和响应的明细
return Logger.Level.FULL;
}
}
这里指定的Level级别是FULL,Feign支持4种级别:
NONE:不记录任何日志信息,这是默认值。
BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
在 consumer-demo 的 UserClient 接口类上的@FeignClient注解中指定配置类:
@FeignClient(value = "user-service",fallback = UserClientFallback.class,configuration = FeignConfig.class)
public interface UserClient {}
四, Spring Cloud Gateway网关
1. 简介
Spring Cloud Gateway的核心就是一系列的过滤器,可以将客户端的请求转发到不同的微服务。主要作用:过滤和路由。
2. 入门案例
目的:搭建网关服务工程测试网关服务作用
需求:通过网关系统heima-gateway将包含有/user的请求路由到 http://127.0.0.1/user/用户id
实现步骤:
- 创建工程
创建工程heima-gateway - 添加启动器依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
- 编写启动引导类和配置文件
package com.xmx.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
- 修改配置文件,设置路由信息
server:
port: 10010
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由id,可以任意
- id: user-service-route
# 代理的服务地址
uri: http://127.0.0.1:9092
# 路由断言:可以匹配映射路径
predicates:
- Path=/user/**
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
instance:
prefer-ip-address: true
- 启动测试
3. 面向服务的路由
目标:使用eureka注册的服务作为路由地址
分析:如果将路由服务地址写死明显是不合理的;在Spring Cloud Gateway中可以通过配置动态路由解决。
面向服务的路由,只需要在配置文件中指定路由路径类似:uri: lb://user-service
server:
port: 10010
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由id,可以任意
- id: user-service-route
# 代理的服务地址
#uri: http://127.0.0.1:9092
# 代理的服务地址;lb表示从eureka中获取具体服务
uri: lb://user-service
# 路由断言:可以匹配映射路径
predicates:
- Path=/user/**
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
instance:
prefer-ip-address: true
lb之后编写的服务名必须要在eureka中注册才能使用,路由配置中uri所用的协议为lb时(以uri: lb://user-service为例),gateway将使用 LoadBalancerClient把user-service通过eureka解析为实际的主机和端口,并进行ribbon负载均衡。
4. 路由前缀处理
目标:可以对请求到网关服务的地址添加或去除前缀
分析:
提供服务的地址:http://127.0.0.1:9091/user/8
添加前缀:对请求地址添加前缀路径之后再作为代理的服务地址;
http://127.0.0.1:10010/8 --> http://127.0.0.1:9091/user/8 添加前缀路径 /user
去除前缀:将请求地址中路径去除一些前缀路径之后再作为代理的服务地址;
http://127.0.0.1:10010/api/user/8 --> http://127.0.0.1:9091/user/8 去除前缀路径 /api
客户端的请求地址与微服务的服务地址如果不一致的时候,可以通过配置路径过滤器实现路径前缀的添加和去除。
在gateway中可以通过配置路由的过滤器PrefixPath,实现映射路径中地址的添加
通过 PrefixPath=/xxx 来指定了路由要添加的前缀。
PrefixPath=/user http://localhost:10010/8 --》http://localhost:9091/user/8
PrefixPath=/user/abc http://localhost:10010/8 --》http://localhost:9091/user/abc/8
server:
port: 10010
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由id,可以任意
- id: user-service-route
# 代理的服务地址
#uri: http://127.0.0.1:9092
# 代理的服务地址;lb表示从eureka中获取具体服务
uri: lb://user-service
# 路由断言:可以匹配映射路径
predicates:
#- Path=/user/**
- Path=/**
filters:
# 添加请求路径的前缀
- PrefixPath=/user
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
instance:
prefer-ip-address: true
在gateway中可以通过配置路由的过滤器StripPrefix,实现映射路径中地址的去除;
通过 StripPrefix=1 来指定了路由要去掉的前缀个数。如:路径 /api/user/1 将会被代理到 /user/1 。
StripPrefix=1 http://localhost:10010/api/user/8 --》http://localhost:9091/user/8
StripPrefix=2 http://localhost:10010/api/user/8 --》http://localhost:9091/8
server:
port: 10010
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由id,可以任意
- id: user-service-route
# 代理的服务地址
#uri: http://127.0.0.1:9092
# 代理的服务地址;lb表示从eureka中获取具体服务
uri: lb://user-service
# 路由断言:可以匹配映射路径
predicates:
#- Path=/user/**
#- Path=/**
- Path=/api/user/**
filters:
# 添加请求路径的前缀
#- PrefixPath=/user
# 1表示过滤1个路径,2表示两个路径,以此类推
- StripPrefix=1
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
instance:
prefer-ip-address: true
5. 过滤器
用法:在配置文件中指定要使用的过滤器名称
类型:局部,全局
使用场景:请求鉴权,异常处理,记录调用时长等
配置全局默认过滤器
server:
port: 10010
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
# 路由id,可以任意
- id: user-service-route
# 代理的服务地址
#uri: http://127.0.0.1:9092
# 代理的服务地址;lb表示从eureka中获取具体服务
uri: lb://user-service
# 路由断言:可以匹配映射路径
predicates:
#- Path=/user/**
#- Path=/**
- Path=/api/user/**
filters:
# 添加请求路径的前缀
#- PrefixPath=/user
# 1表示过滤1个路径,2表示两个路径,以此类推
- StripPrefix=1
# 默认过滤器,对所有路由都生效
default-filters:
- AddResponseHeader=X-Response-Foo, Bar
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
instance:
prefer-ip-address: true
6. 自定义局部过滤器
目标:按照默认过滤器编写并配置一个自定义局部过滤器,该过滤器可以通过配置文件中的参数名称获取请求的参数值
需求:在过滤器(MyParamGatewayFilterFactory)中将http://localhost:10010/api/user/8?name=itcast中的参数name的值获取到并输出到控制台;并且参数名是可变的,也就是不一定每次都是name;需要可以通过配置过滤器的时候做到配置参数名。
实现步骤:
- 配置过滤器
- 编写过滤器
- 测试
7. 自定义全局过滤器
目标:定义一个全局过滤器检查请求中是否携带有token参数
需求:编写全局过滤器,在过滤器中检查请求地址是否携带token参数。如果token参数的值存在则放行;如果token的参数值为空或者不存在则设置返回的状态码为:未授权也不再执行下去。
实现步骤:
8. Gateway其它配置说明
目标:Gateway网关的负载均衡和熔断参数配置
Gateway中默认就已经集成了Ribbon负载均衡和Hystrix熔断机制。但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了。因此建议手动进行配置:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000
ribbon:
ConnectTimeout: 1000
ReadTimeout: 2000
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 0
一般网关都是所有微服务的统一入口,必然在被调用的时候会出现跨域问题。
跨域:在js请求访问中,如果访问的地址与当前服务器的域名、ip或者端口号不一致则称为跨域请求。若不解决则不能获取到对应地址的返回结果。
如:从在http://localhost:9090中的js访问 http://localhost:9000的数据,因为端口不同,所以也是跨域请求。
在访问Spring Cloud Gateway网关服务器的时候,出现跨域问题的话;可以在网关服务器中通过配置解决,允许哪些服务是可以跨域请求的;具体配置如下:
spring:
application:
name: api-gateway
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
#allowedOrigins: * # 这种写法或者下面的都可以,*表示全部
allowedOrigins:
- "http://docs.spring.io"
allowedMethods:
- GET
Gateway网关一般直接给终端请求使用;Feign一般用在微服务之间调用。
四, Spring Cloud Config分布式配置中心
在分布式系统中,由于服务数量非常多,配置文件分散在不同的微服务项目中,管理不方便。为了方便配置文件集中管理,需要分布式配置中心组件。在Spring Cloud中,提供了Spring Cloud Config,它支持配置文件放在配置服务的本地,也支持放在远程Git仓库(GitHub、码云)。
使用Spring Cloud Config配置中心后的架构如下图:
Spring Cloud Config作用:可以通过修改在git仓库中的配置文件实现其他所有微服务的配置文件的修改。
1. 搭建配置中心微服务
创建码云的远程公开git仓库,搭建配置中心微服务config-server
导入依赖:
<dependencies>
<!-- Eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
配置文件
server:
port: 12000
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://gitee.com/xumx123/heima-config.git
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
在gitee中修改了配置文件会在配置中心服务及时更新。
2. 获取配置中心配置
目的:改造用户微服务user-service,配置文件信息不再由微服务项目提供,而是从配置中心获取。
需求:将服务提供工程user-service的application.yml配置文件删除,修改为从配置中心config-server中获取。
实现步骤:
- 添加启动器依赖
- 修改配置文件
- 启动测试
将原本的application.yml删除;然后添加 bootstrap.yml配置文件,该文件也是spring boot的默认配置文件,其内容经常配置一些项目中固定的配置项。如果是项目经常变动的应该配置到application.yml中,现在使用了配置中心则应该配置到git仓库中对应的配置文件。
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
配置文件 bootstrap.yml
spring:
cloud:
config:
# 要与仓库中的配置文件的application保持一致
name: user
# 要与仓库中的配置文件的profile保持一致
profile: dev
# 要与仓库中的配置文件所属的版本(分支)一样
label: master
discovery:
# 使用配置中心
enabled: true
# 配置中心服务名
service-id: config-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
3. Spring Cloud Bus服务总线
Spring Cloud Bus作用:将git仓库的配置文件更新,在不重启系统的情况下实现及时同步到各个微服务。
目的:启动RabbitMQ通过修改码云中的配置文件发送Post请求实现及时更新用户微服务中的配置项
需求:在码云的git仓库中修改user-dev.yml配置文件,实现不重启user-service的情况下可以及时更新配置文件。
实现步骤:
- 启动RabbitMQ
- 修改配置中心config-server
- 修改服务提供工程user-service
- 测试
config-server的依赖添加内容
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
config-server的配置文件添加内容
server:
port: 12000
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://gitee.com/xumx123/heima-config.git
# 配置rabbitmq信息;如果都与默认值一致则不需要配置
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
management:
endpoints:
web:
exposure:
# 暴露触发消息总线的地址
include: bus-refresh
user-service的依赖添加内容
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
user-service的配置文件添加内容
# 配置rabbitmq信息;如果都与默认值一致则不需要配置
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
UserController的修改
上述案例代码已上传至码云:springcloud 中的FeignGatewayConfigBus分支
4. Spring Cloud 体系综合应用
标签:服务,Spring,org,springframework,eureka,user,import,java,Cloud 来源: https://blog.csdn.net/qq_40301475/article/details/115493076
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。