SpringCloud1-了解服务拆解远程调用

SpringCloud01

单体架构:简单方便,高度耦合,扩展性差,适合小型项目。

分布式架构:松耦合,扩展性好,但架构复杂,难度大,适合大型互联网项目。

  • 微服务是一种良好的分布式架构方案

    ①优点:拆分粒度更小、服务更独立、耦合度更低

    ②缺点:架构非常复杂,运维、监控、部署难度提高

  • SpringCloud是微服务架构的一站式解决方案,集成了各种优秀微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验。另外,SpringCloud底层是依赖于SpringBoot的。
    在这里插入图片描述

服务拆分

微服务拆分原则:
- 不同微服务,不要重复开发相同业务
- 微服务数据独立,不要访问其它微服务的数据库
- 微服务可以将自己的业务暴露为接口,供其它微服务调用

示例结构如下:

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

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

要求:

  • 订单微服务和用户微服务都必须有各自的数据库,相互独立
  • 订单服务和用户服务都对外暴露Restful的接口
  • 订单服务如果需要查询用户信息,只能调用用户服务的Restful接口,不能查询用户数据库

1.导入Sql语句

首先,将课前资料提供的cloud-order.sqlcloud-user.sql导入到mysql中:

mysql> select * from cluster_order.tb_order;
+-----+---------+-----------------------------------------+--------+------+
| id  | user_id | name                                    | price  | num  |
+-----+---------+-----------------------------------------+--------+------+
| 101 |       1 | Apple 苹果 iPhone 12                    | 699900 |    1 |
| 102 |       2 | 雅迪 yadea 新国标电动车                 | 209900 |    1 |
| 103 |       3 | 骆驼(CAMEL)休闲运动鞋女               |  43900 |    1 |
| 104 |       4 | 小米10 双模5G 骁龙865                   | 359900 |    1 |
| 105 |       5 | OPPO Reno3 Pro 双模5G 视频双防抖        | 299900 |    1 |
| 106 |       6 | 美的(Midea) 新能效 冷静星II            | 544900 |    1 |
| 107 |       2 | 西昊/SIHOO 人体工学电脑椅子             |  79900 |    1 |
| 108 |       3 | 梵班(FAMDBANN)休闲男鞋                |  31900 |    1 |
+-----+---------+-----------------------------------------+--------+------+
mysql> select * from cluster_user.tb_user;
+----+-----------+-----------------------------+
| id | username  | address                     |
+----+-----------+-----------------------------+
|  1 | 柳岩      | 湖南省衡阳市                |
|  2 | 文二狗    | 陕西省西安市                |
|  3 | 华沉鱼    | 湖北省十堰市                |
|  4 | 张必沉    | 天津市                      |
|  5 | 郑爽爽    | 辽宁省沈阳市大东区          |
|  6 | 范兵兵    | 山东省青岛市                |
+----+-----------+-----------------------------+

cloud-order表中持有cloud-user表中的id字段。

2.导入demo工程

用IDEA导入资料提供的Demo:

\cloud-demo\cloud-demo\user-service\src\main\resources\application.yml
[root@test cloud-demo]# tree user-service
user-service
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── cn
    │   │       └── itcast
    │   │           └── user
    │   │               ├── mapper
    │   │               │   └── UserMapper.java
    │   │               ├── pojo
    │   │               │   └── User.java
    │   │               ├── service
    │   │               │   └── UserService.java
    │   │               ├── UserApplication.java
    │   │               └── web
    │   │                   └── UserController.java
    │   └── resources
    │       └── application.yml
    └── test
        └── java
user-service
[root@test cloud-demo]# cat user-service/src/main/resources/application.yml
server:
  port: 8081        //服务端口
spring:
  datasource:
  //数据库信息,需要链接的数据库cloud_user,账户,密码
    url: jdbc:mysql://192.168.1.17:3306/cloud_user?useSSL=false
    username: admin
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
mybatis:
  type-aliases-package: cn.itcast.user.pojo
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    cn.itcast: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
[root@test cloud-demo]# cat user-service/src/main/java/cn/itcast/user/web/UserController.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) {
      // 根据id查询cluster_user并返回符合id的信息,规则由userService.queryById定义
        return userService.queryById(id);
    }
}
访问接口localhost:8081/user/1
返回数据库里id是1的信息  |  1 | 柳岩      | 湖南省衡阳市  
order-service
[root@test cloud-demo]# cat order-service/src/main/resources/application.yml
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://192.168.1.17:3306/cloud_order?useSSL=false
    username: admin
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
mybatis:
  type-aliases-package: cn.itcast.user.pojo
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    cn.itcast: debug
  pattern:
[root@test cloud-demo]# cat order-service/src/main/java/cn/itcast/order/web/OrderController.java
...
@RestController
@RequestMapping("order")
public class OrderController {

   @Autowired
   private OrderService orderService;

    @GetMapping("{orderId}")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
        // 根据id查询订单cluser_order并返回
        return orderService.queryOrderById(orderId);
    }
}
访问接口localhost:8080/order/101
返回数据库里id是101的信息   | 101 |   1 | Apple 苹果 iPhone 12    | 699900 |    1 |

3.实现远程调用案例

在这里插入图片描述
在order-service中 向user-service发起一个http的请求,调用http://localhost:8081/user/{userId}这个接口。大概的步骤是这样的:

- 注册一个RestTemplate的实例到Spring容器
- 修改order-service服务中的OrderService类中的queryOrderById方法,根据Order对象中的userId查询User
- 将查询的User填充到Order对象,一起返回

4.注册RestTemplate

[root@test cloud-demo]# tree order-service/
order-service/
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── cn
    │   │       └── itcast
    │   │           └── order
    │   │               ├── mapper
    │   │               │   └── OrderMapper.java
    │   │               ├── OrderApplication.java
    │   │               ├── pojo
    │   │               │   ├── Order.java
    │   │               │   └── User.java
    │   │               ├── service
    │   │               │   └── OrderService.java
    │   │               └── web
    │   │                   └── OrderController.java
    │   └── resources
    │       └── application.yml
    └── test
        └── java
[root@test cloud-demo]# cat order-service/src/main/java/cn/itcast/order/pojo/Order.java
package cn.itcast.order.pojo;

import lombok.Data;

@Data
public class Order {
    private Long id;
    private Long price;
    private String name;
    private Integer num;
    private Long userId;		//加入了返回的userid项
    private User user;

首先,我们在order-service服务中的OrderApplication启动类中,注册RestTemplate实例:

[root@test cloud-demo]# cat order-service/src/main/java/cn/itcast/order/OrderApplication.java
...
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

    /**
     * Bean创建RestTemplate实例并注入Spring容器
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

   /* @Bean
    public IRule randomRule() {
        return new RandomRule();
    }*/
}

OrderController.java里的 return orderService.queryOrderById(orderId) 定义了查询指向OrderService
因此修改order-service服务中的cn.itcast.order.service包下的OrderService类中的queryOrderById方法:

[root@test cloud-demo]# cat order-service/src/main/java/cn/itcast/order/service/OrderService.java
...
@Service
public class OrderService {
...
    /*@Autowired
    private RestTemplate restTemplate;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.利用RestTemplate发起http请求,查询用户
        String url = "http://localhost:8081/user/" + order.getUserId();
        // 2.2.发送http请求,实现远程调用
        User user = restTemplate.getForObject(url, User.class);
        // 3.封装user到Order
        order.setUser(user);
        // 4.返回
        return order;
    }*/
}

访问端口时,便能获得需要调用的信息了
但是 String url = “http://localhost:8081/user/” + order.getUserId(); 是硬编码并不利于服务的维护,以及应对调用多实例的服务。比如user-service部署了多个实例。这些问题都需要利用SpringCloud中的注册中心来解决,其中最常用的注册中心就是Eureka以及nacos。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值