微服务≠springcloud,是一种经过良好架构设计的分布式解决方案,微服务架构特征
单体架构
将业务的所有的功能集成到一个项目中开发,打成一个包部署
优点:
缺点:
分布式架构
根据业务功能对系统进行拆分,每个业务模块作为独立项目开发,称为一个服务。
优点:
springcluod是目前全球使用最广泛的微服务框架,集成了各种微服务功能组件,并基于springboot实现了这些组件的自动装配
springcloud与springboot的兼容版本
服务拆分
创建数据库以及执行sql语句的小插曲
创建数据库时,编码使用utf8mb4(我的mysql版本是8.0.33),而给定的资料中是用5版本的mysql导出的sql脚本,因此直接运行可能有些问题。主要是字符集和排序规则的问题,MySQL 8.0 会自动将会话字符集设置为 utf8mb4,因此不需要再手动设置 SET NAMES utf8mb4;mysql5.0常用的字符集是utf8,因此导出的内容可能也涉及utf8字符集的设置,修改为适合MySQL 8.0的utf8mb4即可;另外,不需要再在表级别上设置utf8mb4字符集以及排序规则,我整理了适合5版本以及8版本两个版本的sql脚本
cloud-order数据库 MySQL 5.0版本
-- cloud-order数据库 MySQL 5.0版本
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for tb_order
-- ----------------------------
DROP TABLE IF EXISTS `tb_order`;
CREATE TABLE `tb_order` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单id',
`user_id` bigint(20) NOT NULL COMMENT '用户id',
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称',
`price` bigint(20) NOT NULL COMMENT '商品价格',
`num` int(10) NULL DEFAULT 0 COMMENT '商品数量',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `username`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of tb_order
-- ----------------------------
INSERT INTO `tb_order` VALUES (101, 1, 'Apple 苹果 iPhone 12 ', 699900, 1);
INSERT INTO `tb_order` VALUES (102, 2, '雅迪 yadea 新国标电动车', 209900, 1);
INSERT INTO `tb_order` VALUES (103, 3, '骆驼(CAMEL)休闲运动鞋女', 43900, 1);
INSERT INTO `tb_order` VALUES (104, 4, '小米10 双模5G 骁龙865', 359900, 1);
INSERT INTO `tb_order` VALUES (105, 5, 'OPPO Reno3 Pro 双模5G 视频双防抖', 299900, 1);
INSERT INTO `tb_order` VALUES (106, 6, '美的(Midea) 新能效 冷静星II ', 544900, 1);
INSERT INTO `tb_order` VALUES (107, 2, '西昊/SIHOO 人体工学电脑椅子', 79900, 1);
INSERT INTO `tb_order` VALUES (108, 3, '梵班(FAMDBANN)休闲男鞋', 31900, 1);
SET FOREIGN_KEY_CHECKS = 1;
cloud-order数据库 MySQL 8.0版本
-- cloud-order数据库 MySQL 8.0版本
-- SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for tb_order
-- ----------------------------
DROP TABLE IF EXISTS `tb_order`;
CREATE TABLE `tb_order` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单id',
`user_id` bigint(20) NOT NULL COMMENT '用户id',
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商品名称',
`price` bigint(20) NOT NULL COMMENT '商品价格',
`num` int(10) NULL DEFAULT 0 COMMENT '商品数量',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `username`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 ROW_FORMAT = Compact;
-- ----------------------------
-- Records of tb_order
-- ----------------------------
INSERT INTO `tb_order` VALUES (101, 1, 'Apple 苹果 iPhone 12 ', 699900, 1);
INSERT INTO `tb_order` VALUES (102, 2, '雅迪 yadea 新国标电动车', 209900, 1);
INSERT INTO `tb_order` VALUES (103, 3, '骆驼(CAMEL)休闲运动鞋女', 43900, 1);
INSERT INTO `tb_order` VALUES (104, 4, '小米10 双模5G 骁龙865', 359900, 1);
INSERT INTO `tb_order` VALUES (105, 5, 'OPPO Reno3 Pro 双模5G 视频双防抖', 299900, 1);
INSERT INTO `tb_order` VALUES (106, 6, '美的(Midea) 新能效 冷静星II ', 544900, 1);
INSERT INTO `tb_order` VALUES (107, 2, '西昊/SIHOO 人体工学电脑椅子', 79900, 1);
INSERT INTO `tb_order` VALUES (108, 3, '梵班(FAMDBANN)休闲男鞋', 31900, 1);
SET FOREIGN_KEY_CHECKS = 1;
cloud-user数据库 MySQL 5.0版本
SET NAMES utf8mb4;
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,
`username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人',
`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `username`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES (1, '柳岩', '湖南省衡阳市');
INSERT INTO `tb_user` VALUES (2, '文二狗', '陕西省西安市');
INSERT INTO `tb_user` VALUES (3, '华沉鱼', '湖北省十堰市');
INSERT INTO `tb_user` VALUES (4, '张必沉', '天津市');
INSERT INTO `tb_user` VALUES (5, '郑爽爽', '辽宁省沈阳市大东区');
INSERT INTO `tb_user` VALUES (6, '范兵兵', '山东省青岛市');
SET FOREIGN_KEY_CHECKS = 1;
cloud-user数据库 MySQL 8.0版本
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,
`username` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收件人',
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `username`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 ROW_FORMAT = Compact;
-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES (1, '柳岩', '湖南省衡阳市');
INSERT INTO `tb_user` VALUES (2, '文二狗', '陕西省西安市');
INSERT INTO `tb_user` VALUES (3, '华沉鱼', '湖北省十堰市');
INSERT INTO `tb_user` VALUES (4, '张必沉', '天津市');
INSERT INTO `tb_user` VALUES (5, '郑爽爽', '辽宁省沈阳市大东区');
INSERT INTO `tb_user` VALUES (6, '范兵兵', '山东省青岛市');
SET FOREIGN_KEY_CHECKS = 1;
微服务拆分Demo
1.准备工作
1.创建2个不同的数据库cloud-order与cloud-user
2.导入相应的sql文件
3.导入demo
4.运行两个服务端程序OrderApplication与UserApplication
2.准备工作运行结果
1.远程调用方式分析与案例
用户模块对外暴露接口@GetMapping(“/user/{id}”),只要能够发送HTTP请求即可请求目标地址并获得返回结果
使用RestTemplate对象,可以被直接注入,基础案例
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
// 2.利用RestTemplate发送请求
String url="http://localhost:8081/user/"+order.getUserId();
User user=restTemplate.getForObject(url,User.class);
order.setUser(user);
// 4.返回
return order;
}
}
运行结果
2.提供者与消费者
提供者:暴露接口给别人调用
消费者:调用别人的接口
服务A调用服务B,服务B调用服务C,此时服务B既可以是提供者也是消费者。
3.Eureka注册中心原理
使用硬编码服务地址,后期有多个提供服务的人时,会造成问题…
Eureka的2个概念
Eureka的使用流程
4.搭建Eureka服务
<dependency>
<goupId>org.springframework.cloudgoupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
由于在父工程中已经指定了spring-cloud依赖库,所以里边的各种spring-cloud组件都已经被指定,因此子工程中eureka依赖不需要指定版本。
2.启动类添加@EnableEurekaServer
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class,args);
}
}
3.添加配置信息(**由于eureka本身也是一个微服务,所以在启动时会将自己也注册到eureka上,为了将来eureka集群的使用),需要特别注意设置fetch-registry为false ,否则会报错,因为此时并没有其他服务的信息,所以如果让它拉取会报错, register-with-eureka,fetch-registry默认都为true
server:
port: 10087 # 服务端口
spring:
application:
name: eurekaserver # 服务名称
# eureka服务注册信息
eureka:
client:
register-with-eureka: true # 是否注册自己的信息到EurekaServer
fetch-registry: false # 是否拉取其它服务的信息
service-url:
defaultZone: http://127.0.0.1:10087/eureka
运行结果:
注册到eureka的实例(一个服务每注册一份就是一个实例)
5.服务注册
1.导入依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
2.新增配置,以user-service为例(只需要将服务名称改为对应的服务名称即可),其余同理
spring:
application:
name: userservice # user服务名称
# eureka服务注册信息
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10087/eureka
6.同一个服务多次启动
这是我们当前IDEA的运行面板:
似乎并不是非常的方便,于是我们将其修改为Run Dashboard面板,点击下图所示的“服务”
添加springboot配置即可,运行结果(适用于2020,2021版本):
右键单击一个服务,以orderservice为例,点击“复制配置”
随后弹出窗口
由于启动同样的服务使用同样的端口会造成冲突,所以重新配置新的服务的端口为8082。
点击应用,启动之,运行结果:
此时,在eureka注册中心中配置了2个orderserivce服务
7.服务的发现
比如在orderservice中完成服务拉取,“服务拉取”就是**基于服务名称获取服务列表,然后对服务列表做负载均衡。
String url="http://userservice/user/"+order.getUserId();
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}