1 Spring Cloud 简介,搭建简单的微服务场景并思考

目录

1 简介

 2 模拟微服务业务场景

2.1 创建父工程

2.2 创建服务提供者工程(SringBoot+Mybatis+Web)

2.3 创建服务消费者工程(SringBoot+Web)

2.4 问题思考


1 简介

  • SpringBoot是SpringCloud的基础
  • Spring Cloud是分布式系统开发的工具套件。
  • 主要部分:注册中心、负载均衡、熔断器、远程调用、网关、配置中心、消息总线等
  • 特点:Spring Cloud并没有重复制造轮子,它从架构层面,降低了对大型分布式系统构建的要求和难度,可以用低的成本(技术、硬件)搭建一套高效、分布式、容错的平台,适用于中小型公司。
  • 缺点:不适用于小型项目。

spring cloud 架构如下:

 2 模拟微服务业务场景

  • 开发中的微服务之间的关系实际上就是生产者和消费者关系。接下来,我们要模拟开发过程中的服务间关系,然后进行一些思考。
  • 目标:模拟一个最简单的服务调用场景,场景中包含微服务提供者(Producer)和微服务调用者(Consumer),方便后面学习微服务架构。
  • 注意:实际开发中,每个微服务为一个独立的SpringBoot工程。

接下来会创建三个工程:

  • 父工程:包含下面两个工程(Maven非骨架创建)
  • 服务提供者:对外提供查询用户的服务(SpringBoot创建,SringBoot+Mybatis+Web,坐标勾选DevTools、lombok、web、Mybatis、drive)
  • 服务消费者:调用用户微服务提供的查询用户服务(SpringBoot创建,SringBoot+Web,坐标勾选DevTools、lombok、web)

2.1 创建父工程

2.2 创建服务提供者工程(SringBoot+Mybatis+Web)

  • 创建SpringBoot工程,勾选依赖坐标

  • 创建User表、创建实体User
-- 创建数据库
CREATE database springcloud CHARACTER SET utf8 COLLATE utf8_general_ci;
-- 使用springcloud数据库
USE springcloud;
-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
CREATE TABLE `tb_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL COMMENT '用户名',
  `password` varchar(100) DEFAULT NULL COMMENT '密码',
  `name` varchar(100) DEFAULT NULL COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `sex` int(11) DEFAULT NULL COMMENT '性别,1男,2女',
  `birthday` date DEFAULT NULL COMMENT '出生日期',
  `created` date DEFAULT NULL COMMENT '创建时间',
  `updated` date DEFAULT NULL COMMENT '更新时间',
  `note` varchar(1000) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户信息表';
-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES ('1', 'zhangsan', '123456', '张三', '13', '1', '2006-08-01', '2019-05-16', '2019-05-16', '张三');
INSERT INTO `tb_user` VALUES ('2', 'lisi', '123456', '李四', '13', '1', '2006-08-01', '2019-05-16', '2019-05-16', '李四');

 

  • 编写三层架构:Mapper、Service、controller
@Mapper //该注解的作用:将该类的动态代理实现类注入到spring容器中
public interface UserMapper {
    //根据id查询用户信息
    @Select("select * from tb_user where id=#{id} ")
    User findById(Integer id);
}
public interface UserService {
    User findById(Integer id);
}

 

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public User findById(Integer id) {
        return userMapper.findById(id);
    }
}
/**
 * 用户服务,提供查询用户信息的接口
 */

@RestController
public class UserController {
    @Autowired
    private UserService userService;

    /**
     * 请求参数绑定,举例:假如现在有Http请求:localhost:8080/user/findById?id111123
     * 那么 @RequestParam("id") Integer id 注解的意思是:把id变量和请求参数中的的那个id变量进行绑定
     */
    @RequestMapping("/user/findById")
    public User findById(@RequestParam("id") Integer id){
        return userService.findById(id);
    }
}
  • 编写查询方法,基于注解编写查询语句(直接写在持久层的接口上)
  • 在application.properties中添加配置:端口,数据库连接信息
# 端口
server.port=9091
# 数据库连接配置信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.password=root
spring.datasource.username=root
  • 访问测试地址

http://localhost:9091/user/findById?id=1

2.3 创建服务消费者工程(SringBoot+Web)

消费者工程很简单,没有三层架构,只有一个controller层(外带一个pojo的User对象),该层用来调用服务提供者的controller层的服务。

/**
 * 消费者的控制层,提供服务,访问提供者接口,为真实用户返回信息
 */
@RestController
public class ConsumerController {
    @Autowired
    private RestTemplate restTemplate;

    /**
     *  这个方法做的事情很简单:调用提供者的findById接口获取用户数据
     *  思考:消费者所访问的来自提供者的服务的url地址是硬编码的,如果地址端口变了怎么办?如果服务提供者的服务挂了消费者怎样才能知道呢?
     */
    @RequestMapping("/consumer/{id}")
    public User consumerSendRequest(@PathVariable("id") Integer id){
        String url = "http://localhost:9091/user/findById?id="+id;
        User user = restTemplate.getForObject(url, User.class);
        return user;
    }

    /**
     * 在这里补充一个知识点:
     * 之前的url中通过?后面的内容来表示请求参数,比如:         http://localhost:8080/consumer?id=1
     * 但是呢,restful风格要求不能用问号,于是参数也要一直往后写:http://localhost:8080/consumer/1
     * 然后获取到这个请求参数的格式也从原来的 “public User findById(@RequestParam("id") Integer id)”
     * 转变成如下的形式:@RequestMapping中的参数用大括号括起来,然后和@PathVariable注解配合使用
     */
//    @RequestMapping("/consumer/{id}")
//    public Integer consumerSendRequest2(@PathVariable("id") Integer id){
//        System.out.println(id);
//        return id;
//    }
}

思考:消费者所访问的来自提供者的服务的url地址是硬编码的,如果地址端口变了怎么办?如果服务提供者的服务挂了消费者怎样才能知道呢?其实问题还不止这些,往下看。

2.4 问题思考

  • 在消费者服务中,访问提供者服务URL地址的硬编码、服务消费者不清楚服务提供者状态
  • 为增加服务并发访问量,搭建集群,集群的负载均衡怎么实现?
  • 服务提供者如果出现故障,会不会向用户抛出异常页面,该不该抛出错误页面?
  • RestTemplate这种请求调用方式是否还有优化空间?从复用,管理,可读性角度来思考
  • 多服务权限拦截如何实现?怎么保证所有微服务服务的安全性?
  • 众多微服务的配置文件,每次都修改很多个,是不是很麻烦?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值