前言
随着互联网的发展,网站应用的规模也在不断的扩大,进而导致系统架构也在不断的进行变化;
互联网早期,一般的网站应用流量较小,只需一个应用,将所有功能代码都部署在一起就可以,这样可以减少开发、部署和维护的成本。
比如说一个电商网站,里面会包含很多用户管理,商品管理,订单管理,物流管理等等很多模块,我们会把它们做成1个web项目,然后部署到1台Tomcat上。
1.2.缺点
还是以上面的电商为例子,用户访问量的增加可能影响的只是用户和订单模块,但是对消息模块的影响就比较小。
那么此时我们希望只多增加几个订单模块,而不增加消息模块,此时单体应用就做不到了,垂直应用就应运而生了。
所谓的垂直应用架构,就是将原来的一个应用拆成互不相干的几个应用,比如我们可以将上面电商的单体应用拆分成
-
电商系统(用户管理 商品管理 订单管理)
-
后台系统(用户管理 订单管理 客户管理)
-
CMS系统(广告管理 营销管理)
2.2.缺点
3.2.缺点
4.2.缺点
5.2.缺点
-
单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发
-
面向服务:微服务对外暴露业务接口
-
自治:团队独立(不同的团队负责不同的模块开发维护)、技术独立(可使用不同的编程语言实现不同的子模块)、数据独立(每个子模块使用不同的数据库)、部署独立(每个子模块可部署到不同的服务器上)
-
-
这么多小服务,如何管理他们?服务治理(电话本)
-
这么多小服务,他们之间如何通讯?(RPC/HTTP-->RestTemplate)
-
这么多小服务,客户端怎么访问他们?(服务网关)
三、实现微服务的方案
目前最知名的就是SpringCloud和SpringCloudAlibaba
-
SpringCloud:Spring基于NetFlix微服务组件进行封装,提供微服务一站式解决方案
-
-
-
独立数据库:微服务数据独立,不要访问其它微服务的数据库
-
1.1.创建微服务
springcloud-demo:父工程,管理依赖
-
order-service:订单微服务,负责订单相关业务
-
/* Navicat Premium Data Transfer Source Server : local Source Server Type : MySQL Source Server Version : 50622 Source Host : localhost:3306 Source Schema : heima Target Server Type : MySQL Target Server Version : 50622 File Encoding : 65001 Date: 01/04/2021 14:57:18 */ create database cloud_order; use cloud_order; 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.sql
/* Navicat Premium Data Transfer Source Server : local Source Server Type : MySQL Source Server Version : 50622 Source Host : localhost:3306 Source Schema : heima Target Server Type : MySQL Target Server Version : 50622 File Encoding : 65001 Date: 01/04/2021 14:57:18 */ create database cloud_user; use cloud_user; 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.sql
1.3.pom依赖
springcloud-demo
<?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.itheima</groupId> <artifactId>springcloud-demo</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>order-service</module> <module>user-service</module> </modules> <!-- 继承springboot --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.9.RELEASE</version> <relativePath/> </parent> <!-- 版本常量 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR10</spring-cloud.version> <mysql.version>5.1.47</mysql.version> <mybatis-plus.version>3.4.0</mybatis-plus.version> <spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.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</scope> </dependency> <!-- 继承springCloudAlibaba --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!--mybatisPlus 起步依赖--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> </dependency> </dependencies> </dependencyManagement> <!--依赖管理--> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> </project>
pom.xml
order-service
<?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-demo</artifactId> <groupId>com.itheima</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>order-service</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
pom.xml
user-service
<?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-demo</artifactId> <groupId>com.itheima</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>user-service</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
pom.xml
在服务调用关系中,会有2个不同的角色;
-
-
服务消费者:
注意:在微服务中服务提供者与服务消费者的角色并不是绝对的,而是相对于业务而言。
-
Apache的一个网络框架,网络请求做了完善的封装,api众多,但是代码复杂 。
-
OkHttp
高效的HTTP客户端,它能允许同一ip和端口的请求重用一个socket,这样能够降低网络连接的时间
-
RestTemplate
1.6.代码实现
1.6.1.注入RestTemplate对象
SpringBoot启动类就是1个配置类,因此可以在启动类中向IOC容器注入RestTemplate 对象
package com.itheima.order; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @MapperScan(\"com.itheima.order.mapper\") @SpringBootApplication public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); } //SpringBoot启动是,在Spring容器中放入1个restTemplate对象 @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
OrderApplication.java
1.6.2.OrderService调用用户微服务
@Service public class OrderService { @Autowired private OrderMapper orderMapper; @Autowired private RestTemplate restTemplate; public Order findById(Long orderId) { // 1.查询订单 Order order = orderMapper.selectById(orderId); //2.调用user-service服务查询当前订单的用户信息 String url = \"http://127.0.0.1:8081/user/\" + order.getUserId(); User user = restTemplate.getForObject(url, User.class); //3.user封装到order对象 order.setUser(user); // 4.返回 return order; } }
RestTemplate
-
一旦服务提供者地址变化,就需要手工修改代码
-
一旦是多个服务提供者,无法实现负载均衡功能
-
一旦服务变得越来越多,人工维护调用关系困难
那么应该怎么解决呢? 这时候就需要通过注册中心动态的实现服务治理
-
服务注册:在服务治理框架中,都会构建1个注册中心(电话本),每个微服务单元向注册中心登记自己提供服务的详细信息。并在注册中心形成1张服务的清单,服务注册中心需要以心跳的方式去监测清单中的服务是否可用,如果不可用,需要在服务清单中剔除不可用的服务。
-
服务发现:
Eureka是SpringCloud技术栈中提供的用作注册中心的组件,它可以实现微服务的自动注册、发现、状态监控。
-
Eureka-Server:就是服务注册中心(可以是一个集群),对外暴露自己的地址。
-
提供者:服务提供方,它启动后向Eureka注册自己信息(地址,服务名称等),并且定期进行服务续约(提供者定期通过http方式向Eureka刷新自己的状态)
-
<dependencies> <!--euraka服务端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies>
3.2.application.yml
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
client:
# 注册中心的职责是维护服务实例,不需要去检索服务
fetch-registry: false
# 默认设置下,注册中心会将自己作为客户端来尝试注册自己,设置为false代表不向注册中心注册自己
register-with-eureka: false
参考
来源:https://www.cnblogs.com/sss4/p/16411823.html
本站部分图文来源于网络,如有侵权请联系删除。