SA实战 ·《SpringCloud Alibaba实战》服务治理(二)

Pike_Chen
发布于 2022-5-31 16:31
浏览
0收藏

 

改造其他微服务
我们可以用同样的方式来改造商品微服务和订单微服务的代码,改造好之后,分别启动商品微服务和订单微服务,并再次刷新Nacos的页面,如下所示。

SA实战 ·《SpringCloud Alibaba实战》服务治理(二)-鸿蒙开发者社区

 

可以看到,用户微服务、商品微服务和订单微服务都已成功注册到Nacos。

实现服务发现
按照整个项目的执行流程,用户执行下单操作时,订单微服务会调用用户微服务的接口获取用户的基本信息,会调用商品微服务的接口获取商品的基本信息。

在订单微服务中校验用户的合法性和校验商品库存是否充足,如果用户合法并且商品库存充足,就会向订单数据表中记录订单信息并调用商品微服务的接口来扣减商品的库存。

用户微服务和商品微服务作为服务的提供者,而订单微服务作为服务的消费者,如果要实现服务的发现功能,我们还需要对订单微服务的代码进行改造。将订单微服务中硬编码的用户微服务和商品微服务的IP地址和端口号修改成从Nacos中获取。

为了让小伙伴们能够更好的对比修改前和修改后的代码,这里,并没有在订单微服务的 io.binghe.shop.order.service.impl#OrderServiceImpl 类上直接修改,还是将其重命名为 io.binghe.shop.order.service.impl.OrderServiceV1Impl 类,同时,再次将其复制一份并命名为io.binghe.shop.order.service.impl.OrderServiceV2Impl类,在后续的开发过程中,如果涉及到大的代码变动,都会以这种方式进行更新。

注入服务发现类
(1)在io.binghe.shop.order.service.impl.OrderServiceV2Impl 类中首先注入DiscoveryClient类的对象,如下所示。

@Autowired
private DiscoveryClient discoveryClient;

创建动态服务地址方法
在io.binghe.shop.order.service.impl.OrderServiceV2Impl 类中创建一个从Nacos中通过服务名称获取IP和端口号的方法getServiceUrl(),并在getServiceUrl()方法中将IP和端口号拼接成IP:PORT的形式,如下所示。

private String getServiceUrl(String serviceName){
    ServiceInstance serviceInstance = discoveryClient.getInstances(serviceName).get(0);
    return serviceInstance.getHost() + ":" + serviceInstance.getPort();
}

具体的实现方式就是调用DiscoveryClient对象的getInstances()方法,并传入服务的名称,从Nacos注册中心中获取一个ServiceInstance类型的List集合,从List集合中获取第1个元素,也就是从List集合中获取到一个ServiceInstance对象,从ServiceInstance对象中获取到IP地址和端口号,并将其拼接成IP:PORT的形式。

定义服务提供者名称
在io.binghe.shop.order.service.impl.OrderServiceV2Impl 类中定义两个成员变量userServer和productServer,表示用户微服务和商品微服务的服务名称,并将其分别复制为server-user和server-product。

private String userServer = "server-user";
private String productServer = "server-product";

注意:userServer的值需要与用户微服务下的application.yml文件中的如下配置的值相同。

spring:
  application:
    name: server-user

productServer的值需要与商品微服务下的application.yml文件中的如下配置的值相同。

spring:
  application:
    name: server-product

修改提交订单逻辑
在io.binghe.shop.order.service.impl.OrderServiceV2Impl 类的saveOrder()方法中,将硬编码的用户微服务和商品微服务的IP和端口修改成从Nacos注册中心中获取,涉及改动的代码片段如下所示。

(1)添加获取用户微服务与商品微服务的IP和端口号的代码片段,如下所示。

//从Nacos服务中获取用户服务与商品服务的地址
String userUrl = this.getServiceUrl(userServer);
String productUrl = this.getServiceUrl(productServer);

(2)修改使用restTemplate获取用户信息的代码片段,修改前的代码片段如下所示。

User user = restTemplate.getForObject("http://localhost:8060/user/get/" + orderParams.getUserId(), User.class);
if (user == null){
    throw new RuntimeException("未获取到用户信息: " + JSONObject.toJSONString(orderParams));
}

修改后的代码片段如下所示。

User user = restTemplate.getForObject("http://" + userUrl + "/user/get/" + orderParams.getUserId(), User.class);
if (user == null){
    throw new RuntimeException("未获取到用户信息: " + JSONObject.toJSONString(orderParams));
}

可以看到,订单微服务获取用户微服务信息时,不再是硬编码用户微服务的IP地址和端口号了。

(3)修改使用restTemplate获取商品信息的代码片段,修改前的代码片段如下所示。

Product product = restTemplate.getForObject("http://localhost:8070/product/get/" + orderParams.getProductId(), Product.class);
if (product == null){
    throw new RuntimeException("未获取到商品信息: " + JSONObject.toJSONString(orderParams));
}

修改后的代码片段如下所示。

Product product = restTemplate.getForObject("http://" + productUrl + "/product/get/" + orderParams.getProductId(), Product.class);
if (product == null){
    throw new RuntimeException("未获取到商品信息: " + JSONObject.toJSONString(orderParams));
}

可以看到,订单微服务获取商品微服务信息时,不再是硬编码商品微服务的IP地址和端口号了。

(4)修改使用restTemplate扣减商品库存的代码片段,修改前的代码片段如下所示。

Result<Integer> result = restTemplate.getForObject("http://localhost:8070/product/update_count/" + orderParams.getProductId() + "/" + orderParams.getCount(), Result.class);
if (result.getCode() != HttpCode.SUCCESS){
    throw new RuntimeException("库存扣减失败");
}

修改后的代码片段如下所示。

Result<Integer> result = restTemplate.getForObject("http://" + productUrl + "/product/update_count/" + orderParams.getProductId() + "/" + orderParams.getCount(), Result.class);
if (result.getCode() != HttpCode.SUCCESS){
    throw new RuntimeException("库存扣减失败");
}

可以看到,订单微服务调用商品微服务的扣减商品库存接口时,不再是硬编码商品微服务的IP地址和端口号了。

注意:修改后的io.binghe.shop.order.service.impl.OrderServiceV2Impl 类的完整源码,小伙伴们可自行查看项目代码,冰河在这里不再赘述。

至此,整个项目就改造完成了。接下来,我们进行测试。

测试项目
开发完成后,我们对快速搭建并开发完成的三大微服务进行简单的测试,在测试之前我们需要先在数据表中添加一些测试数据。

添加测试数据
(1)在用户表中添加一条id为1001的记录,如下所示。

INSERT INTO `shop`.`t_user`(`id`, `t_username`, `t_password`, `t_phone`, `t_address`) VALUES (1001, 'binghe', 'c26be8aaf53b15054896983b43eb6a65', '13212345678', '北京');

(2)在商品数据表中添加几条商品记录,如下所示。

INSERT INTO `shop`.`t_product`(`id`, `t_pro_name`, `t_pro_price`, `t_pro_stock`) VALUES (1001, '华为', 2399.00, 100);
INSERT INTO `shop`.`t_product`(`id`, `t_pro_name`, `t_pro_price`, `t_pro_stock`) VALUES (1002, '小米', 1999.00, 100);
INSERT INTO `shop`.`t_product`(`id`, `t_pro_name`, `t_pro_price`, `t_pro_stock`) VALUES (1003, 'iphone', 4999.00, 100);

测试库存不足的情况
(1)分别启动用户微服务、商品微服务和订单微服务。

(2)查询id为1001的商品信息,如下所示。

mysql> select * from t_product where id = 1001;
+------+------------+-------------+-------------+
| id   | t_pro_name | t_pro_price | t_pro_stock |
+------+------------+-------------+-------------+
| 1001 | 华为       |     2399.00 |         100 |
+------+------------+-------------+-------------+
1 row in set (0.00 sec)

可以看到,id为1001的商品的库存为100。

(3)查询订单表和订单条目表中的数据,如下所示。

  • 查询订单表
    mysql> select * from t_order;
    Empty set (0.00 sec)​

可以看到,订单数据表的数据为空。

  • 查询订单条目表
    mysql> select * from t_order_item;
    Empty set (0.00 sec)​

可以看到,订单条目数据表的数据为空。

(4)在浏览器中调用订单微服务的下单接口,传入的商品数量为1001,如下所示。

SA实战 ·《SpringCloud Alibaba实战》服务治理(二)-鸿蒙开发者社区

 

可以看到,返回的信息中,code为500,codeMsg输出的信息为执行失败,data返回的结果为商品库存不足,并且输出了提交的参数信息。

(5)再次查询id为1001的商品信息,如下所示。

mysql> select * from t_product where id = 1001;
+------+------------+-------------+-------------+
| id   | t_pro_name | t_pro_price | t_pro_stock |
+------+------------+-------------+-------------+
| 1001 | 华为       |     2399.00 |         100 |
+------+------------+-------------+-------------+
1 row in set (0.00 sec)

可以看到,商品id为1001的商品库存仍为100,并没有减少。

(6)再次查询订单表和订单条目表中的数据,如下所示。

  • 查询订单表
    mysql> select * from t_order;
    Empty set (0.00 sec)​

可以看到,订单数据表的数据为空。

  • 查询订单条目表
    mysql> select * from t_order_item;
    Empty set (0.00 sec)​

可以看到,订单条目数据表的数据为空。

综上,当提交订单时传入的商品数量大于商品的库存数量时,系统会抛出异常,并不会执行提交订单和扣减库存的操作。

测试正常下单的情况
(1)在测试库存不足的情况的基础上,我们将调用提交订单的接口时传入的商品数量修改为10,如下所示。

SA实战 ·《SpringCloud Alibaba实战》服务治理(二)-鸿蒙开发者社区

 

可以看到,当商品库存充足时,调用订单微服务的下单接口,返回的数据为success表示下单成功。

(2)再次查询id为1001的商品信息,如下所示。

mysql> select * from t_product where id = 1001;
+------+------------+-------------+-------------+
| id   | t_pro_name | t_pro_price | t_pro_stock |
+------+------------+-------------+-------------+
| 1001 | 华为       |     2399.00 |          90 |
+------+------------+-------------+-------------+
1 row in set (0.00 sec)

可以看到,id为1001的商品库存由原来的100变更为90,减少了10个库存。

(3)再次查询订单表和订单条目表中的数据,如下所示。

  • 查询订单表
mysql> select * from t_order;
+------------------+-----------+-------------+-------------+-----------+---------------+
| id               | t_user_id | t_user_name | t_phone     | t_address | t_total_price |
+------------------+-----------+-------------+-------------+-----------+---------------+
| 3270016896208896 |      1001 | binghe      | 13212345678 | 北京      |      23990.00 |
+------------------+-----------+-------------+-------------+-----------+---------------+
1 row in set (0.00 sec)

可以看到,订单数据表中成功记录了订单的信息

  • 查询订单条目表
    mysql> select * from t_order_item;
    +------------------+------------------+----------+------------+-------------+----------+
    | id               | t_order_id       | t_pro_id | t_pro_name | t_pro_price | t_number |
    +------------------+------------------+----------+------------+-------------+----------+
    | 3270017277890560 | 3270016896208896 |     1001 | 华为       |     2399.00 |       10 |
    +------------------+------------------+----------+------------+-------------+----------+
    1 row in set (0.00 sec)​

可以看到,订单条目数据表中成功记录了订单条目的信息。

至此,项目的测试完毕。

另外,小伙伴们在【冰河技术】知识星球获取到源码后,可以自行测试其他异常情况,比如商品不存在的异常和用户不存在的异常,或者自行验证几个其他的异常情况,看提交是否提交,商品库存是否扣减了。

这次,我们只是使用SpringBoot快速搭建了三个微服务项目,从下一篇开始,我们就要逐渐接入SpringCloud Alibaba技术了,小伙伴们,你们准备好了吗?加入【冰河技术】知识星球,一起搞定《SpringCloud Alibaba实战》吧,加油!!

关于星球
最近,冰河创建了【冰河技术】知识星球,《SpringCloud Alibaba实战》专栏的源码获取方式会放到知识星期中,同时在微信上会创建专门的知识星球群,冰河会在知识星球上和星球群里解答球友的提问。

 

文章转自公众号:冰河技术

分类
已于2022-5-31 16:31:19修改
收藏
回复
举报
回复
    相关推荐