百木园-与人分享,
就是让自己快乐。

微服务介绍

前言

随着互联网的发展,网站应用的规模也在不断的扩大,进而导致系统架构也在不断的进行变化;

 

一、微服务介绍

从互联网早起到现在,系统架构大体经历了下面几个过程: 单体应用架构--->垂直应用架构--->分布式架构--->SOA架构--->微服务架构

1.单体应用架构

互联网早期,一般的网站应用流量较小,只需一个应用,将所有功能代码都部署在一起就可以,这样可以减少开发、部署和维护的成本。

比如说一个电商网站,里面会包含很多用户管理,商品管理,订单管理,物流管理等等很多模块,我们会把它们做成1个web项目,然后部署到1台Tomcat上

1.1.优点

项目架构简单,小型项目的话, 开发成本低;项目部署在一个节点上, 维护方便

1.2.缺点

全部功能集成在1个工程中,对于大型项目来讲上限之后,无法针对不同模块进行针性的性优化和水平扩展;

 

2.垂直应用架构

随着访问量的逐渐增大,单一应用只能依靠增加节点来应对,但是这时候会发现并不是所有的模块都会有比较大的访问量。

还是以上面的电商为例子,用户访问量的增加可能影响的只是用户和订单模块,但是对消息模块的影响就比较小。

那么此时我们希望只多增加几个订单模块,而不增加消息模块,此时单体应用就做不到了,垂直应用就应运而生了。

所谓的垂直应用架构,就是将原来的一个应用拆成互不相干的几个应用,比如我们可以将上面电商的单体应用拆分成

  • 电商系统(用户管理 商品管理 订单管理)

  • 后台系统(用户管理 订单管理 客户管理)

  • CMS系统(广告管理 营销管理)

这样拆分完毕之后,一旦用户访问量变大,只需要增加电商系统的节点就可以了,而无需增加后台和CMS的节点。

 

 

 

2.1.优点

系统拆分实现了流量分担,解决了并发问题,而且可以针对不同模块进行优化和水平扩展;

2.2.缺点

系统之间相互独立,子模块之间无法相互调用,扩展新模块是需要重复开发依赖模块;

 

3.分布式架构

当垂直应用越来越多,重复的业务代码就会越来越多。这时候,我们就思考可不可以将重复的代码抽取出来,做成统一的业务层作为独立的服务,然后由前端控制层调用不同的业务层服务呢?

这就产生了新的分布式系统架构。它将把工程拆分成表现层和服务层两个部分,服务层中包含业务逻辑。表现层只需要处理和页面的交互,业务逻辑都是调用服务层的服务来实现。

 

 

3.1.优点

抽取公共的功能为服务层,提高代码复用性

3.2.缺点

系统间耦合度变高,调用关系错综复杂,难以维护

 

4.SOA架构

在分布式架构下,当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心对集群进行实时管理。

此时,用于资源调度和治理中心(SOA即Service Oriented Architecture,面向服务的架构)是关键。

4.1.优点

使用注册中心解决了服务间调用关系的自动调节;

4.2.缺点

服务间会有依赖关系,一旦某个环节出错会影响较大,服务关系复杂,运维、测试部署困难;

 

5.微服务架构

微服务架构在某种程度上是面向服务的架构SOA继续发展的下一步,它更加强调服务的\"彻底拆分

简单的说就是将单体应用进一步拆分,拆分成更小的服务,每个服务都是1个可以独立运行的项目。

 

5.1.优点

服务原子化拆分,独立打包、部署和升级,保证每个微服务清晰的任务划分,利于扩展

5.2.缺点

分布式系统开发的技术成本高;

 

二、认识微服务

微服务架构,就是将应用拆分成无法再继续拆分的微服务,每个服务都是一个可以独立运行的项目。其主要特点如下:

  • 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发

  • 面向服务:微服务对外暴露业务接口

  • 自治:团队独立(不同的团队负责不同的模块开发维护)、技术独立(可使用不同的编程语言实现不同的子模块)、数据独立(每个子模块使用不同的数据库)、部署独立(每个子模块可部署到不同的服务器上)

  • 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题 

一旦采用微服务系统架构,就势必会遇到这样几个问题:

  • 这么多小服务,如何管理他们?服务治理(电话本)

  • 这么多小服务,他们之间如何通讯?(RPC/HTTP-->RestTemplate)

  • 这么多小服务,客户端怎么访问他们?(服务网关)

对于上面的问题,是任何一个微服务设计者都不能绕过去的,因此大部分的微服务产品都针对以上几个问题,提供了相应的组件来解决它们。

 

三、实现微服务的方案

微服务这种方案需要具体的技术框架来落地,全球的互联网公司都在积极尝试自己的微服务落地技术。

目前最知名的就是SpringCloud和SpringCloudAlibaba

  • SpringCloud:Spring基于NetFlix微服务组件进行封装,提供微服务一站式解决方案

  • SpringCloudAlibaba:在SpringCloud NetFlix基础上封装了阿里巴巴的微服务解决方案 

 

四、微服务环境搭建

微服务的构建应遵循以下原则:

  • 单一职责:不同微服务,不要重复开发相同业务

  • 独立数据库:微服务数据独立,不要访问其它微服务的数据库

  • 暴露接口:微服务可以将自己的业务暴露为接口,供其它微服务调用

1.微服务构建示例

今日我来实现一个简单的微服务调用,以用户模块和订单模块这2个模块为例

1.1.创建微服务项目

springcloud-demo:父工程,管理依赖

  • order-service:订单微服务,负责订单相关业务

  • user-service: 用户微服务,负责用户相关业务

1.2.导入数据库

cloud_order数据库

微服务介绍微服务介绍

/*
 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

cloud_user数据库

微服务介绍微服务介绍

/*
 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 

1.4.实现远程调用

根据订单id查询订单的同时,把订单所属的用户信息一起返回

 

 

在服务调用关系中,会有2个不同的角色;

  • 服务提供者:被其它微服务调用的服务

  • 服务消费者:调用其它微服务的服务

注意:在微服务中服务提供者与服务消费者的角色并不是绝对的,而是相对于业务而言。

1.5.技术分析

order-service服务向user-service服务发起1个HTTP的请求,调用user-service服务的http://localhost:8081/user/{userId}接口;

  • HttpClient

    Apache的一个网络框架,网络请求做了完善的封装,api众多,但是代码复杂 。

  • OkHttp

    高效的HTTP客户端,它能允许同一ip和端口的请求重用一个socket,这样能够降低网络连接的时间

  • RestTemplate

    Spring提供的用于访问Rest服务的客户端,提供多种便捷访问远程Http服务的方法,大大提高客户端的编写效率

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调用用户微服务

在OrderService中调用用户微服务的方法http://localhost:8081/user/{userId},根据id获取user对象

@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;
    }
}

五、Eureka注册中心实现服务治理

当前已经可以通过RestTemplate实现微服务之间的调用,但是服务提供者的网络地址(ip,端口)等硬编码到了代码中,这种做法存在许多问题:

  • 一旦服务提供者地址变化,就需要手工修改代码

  • 一旦是多个服务提供者,无法实现负载均衡功能

  • 一旦服务变得越来越多,人工维护调用关系困难

那么应该怎么解决呢? 这时候就需要通过注册中心动态的实现服务治理

1.服务治理

服务治理是微服务架构中最核心最基本的模块。用于实现各个微服务的自动化服务注册与服务发现

  • 服务注册在服务治理框架中,都会构建1个注册中心(电话本),每个微服务单元向注册中心登记自己提供服务的详细信息。并在注册中心形成1张服务的清单,服务注册中心需要以心跳的方式去监测清单中的服务是否可用,如果不可用,需要在服务清单中剔除不可用的服务。

  • 服务发现服务调用方向服务注册中心咨询服务,并获取所有服务的实例清单,实现对具体服务实例的访问。

 

 

 

2.Eureka简介

Eureka是SpringCloud技术栈中提供的用作注册中心的组件,它可以实现微服务的自动注册、发现、状态监控

  • Eureka-Server:就是服务注册中心(可以是一个集群),对外暴露自己的地址。

  • 提供者:服务提供方,它启动后向Eureka注册自己信息(地址,服务名称等),并且定期进行服务续约(提供者定期通过http方式向Eureka刷新自己的状态)

  • 消费者:服务调用方,它会定期去Eureka拉取服务列表,然后使用负载均衡算法选出一个服务进行调用。

 

3.搭建Eureka服务端

通过源码的方式搭建1个Eureak注册中心,实现微服务的治理;

3.1.pom依赖

  <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

 

六、Nacos注册中心实现服务治理

 

 

参考


来源:https://www.cnblogs.com/sss4/p/16411823.html
本站部分图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » 微服务介绍

相关推荐

  • 暂无文章