初识微服务

什么是微服务?

微服务是一种经过良好设计的分布式架构方案,微服务架构有以下特征:

  • 单一职责:微服务拆分力粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发。
  • 面向服务:微服务对外暴露业务接口。
  • 自治:团队独立、技术独立、数据独立、部署独立

微服务架构&单体架构

单体架构

将业务的所有功能集中在一个项目中开发,打成一个包部署。

优点:

架构简单、部署成本低
缺点:

耦合度高。

分布式架构

根据业务功能对系统进行拆分,每个业务模块作为独立项目开发,称为一个服务。

优点:

  • 降低服务耦合
  • 有利于服务升级拓展。

微服务技术栈

SpringCloud

SpringCloud是微服务架构落地的一套技术栈。它集成了微服务组件各种功能,并基于SpringBoot实现类这些组件的自动装配,从而提供了良好的开箱即用体验。

版本对应关系

SpringCloud、SpringBoot之间的版本对应关系

官网

SpringCloud、SpringBoot、Spring Cloud Alibaba之间的版本对应关系
查看网址

常用组件表

用途 组件名称
服务注册发现 eureka、nacos、consul
服务的负载均衡 ribbon、dubbo
服务的远程调用 openFeign、dubbo
服务熔断降级 hystrix、sentinel
服务网关 gateway、sentinel
服务配置统一管理 config-server、nacos、apollo
服务消息总线 bus
服务安全组件 security、Oauth2.0
服务监控 admin、jvm
链路追踪 sleuth + zipkin

服务拆分及远程调用

服务拆分的注意事项:

  • 不同微服务,不要重复开发相同业务。
  • 微服务数据独立,不要访问其他微服务的数据库
  • 微服务可以将自己的业务暴露为接口,供其他微服务调用

实例

数据准备

数据库cloud_user

sql 复制代码
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;

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, '范兵兵', '山东省青岛市');

数据库cloud_order

sql 复制代码
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);
后端准备
配置文件application.yaml

order

yaml 复制代码
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
mybatis:
  type-aliases-package: com.louis.user.pojo
  configuration:
    map-underscore-to-camel-case: true

user

yaml 复制代码
server:
  port: 8081
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
    username: root
    password: zkpk
    driver-class-name: com.mysql.jdbc.Driver
mybatis:
  type-aliases-package: com.louis.user.pojo
  configuration:
    map-underscore-to-camel-case: true
order-service
实体类

order

java 复制代码
@Data
public class Order {
    private Long id;
    private Long price;
    private String name;
    private Integer num;
    private Long userId;
    private User user;
}

user

java 复制代码
@Data
public class User {
    private Long id;
    private String username;
    private String address;
}
mapper
java 复制代码
public interface OrderMapper {

    @Select("select * from tb_order where id = #{id}")
    Order findById(Long id);
}
service
java 复制代码
@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 4.返回
        return order;
    }
}
controller
java 复制代码
@RestController
@RequestMapping("order")
public class OrderController {

   @Autowired
   private OrderService orderService;

    @GetMapping("{orderId}")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
        // 根据id查询订单并返回
        return orderService.queryOrderById(orderId);
    }
}
user-service
实体类

user

java 复制代码
@Data
public class User {
    private Long id;
    private String username;
    private String address;
}
mapper
java 复制代码
public interface UserMapper {
    
    @Select("select * from tb_user where id = #{id}")
    User findById(@Param("id") Long id);
}
service
java 复制代码
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public User queryById(Long id) {
        return userMapper.findById(id);
    }
}
controller
java 复制代码
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 路径: /user/110
     *
     * @param id 用户id
     * @return 用户
     */
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id) {
        return userService.queryById(id);
    }
}

主程序中使用@MapperScan("xxx")来扫描你的mapper文件,如:@MapperScan("cn.itcast.user.mapper")

测试

运行user

运行order

总结

由运行结果中可以看到,在order中不能显示对应user的数据,由于两个服务是相互分离的,并不清楚在另一个表中的数据信息。所以需要使用到远程调用方式(RestTemplate)。(在订单表服务模块使用java代码的方式向用户模块发起请求)

订单服务添加配置类
java 复制代码
package com.louis.order.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * 创建RestTemplate并注入容器
 * @author XRY
 * @date 2023年07月21日14:28
 */

@Configuration
public class Template {
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
修改OrderService
java 复制代码
@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发起http请求,查询用户
        //url路径
        String url = "http://localhost:8081/user/" + order.getUserId();
        System.out.println("url = " + url);
        //发送http请求,实现远程调用,不同的请求使用不同的xxxForObject,url和浏览器中输入是一样的
        User user = restTemplate.getForObject(url, User.class);
        order.setUser(user);
        // 4.返回
        return order;
    }
}
服务提供者和消费者

想要实现跨服务远程调用,就是发送一次http的请求,就涉及到了服务提供者和服务消费者。
服务提供者:一次业务中,被其他微服务调用的服务。(提供接口给其他微服务。)
服务消费者:一次业务中,调用其他微服务的服务。(调用其他微服务提供的接口)

在上面的示例中,order_service调用user_service的接口,所以order_service是服务消费者,而user_service是服务提供者。

提供者与消费者的角色是相对的,对于不同的业务来说,一个服务既可以是提供者也可以是消费者。

相关推荐
字节源流22 分钟前
【spring cloud Netflix】Eureka注册中心
云原生·eureka
基哥的奋斗历程2 小时前
kubernetes configMap 存储
云原生·容器·kubernetes
Java技术小馆3 小时前
如何设计一个本地缓存
java·面试·架构
数据智能老司机3 小时前
CockroachDB权威指南——SQL调优
数据库·分布式·架构
数据智能老司机3 小时前
CockroachDB权威指南——应用设计与实现
数据库·分布式·架构
数据智能老司机4 小时前
CockroachDB权威指南——CockroachDB 模式设计
数据库·分布式·架构
mghio15 小时前
Dubbo 中的集群容错
java·微服务·dubbo
uhakadotcom17 小时前
视频直播与视频点播:基础知识与应用场景
后端·面试·架构
沉登c20 小时前
第 3 章 事务处理
架构
阿里云云原生20 小时前
LLM 不断提升智能下限,MCP 不断提升创意上限
云原生