赞
踩
3.2、springcloud与springboot版本兼容关系
现在还有一个问题:就是我们怎么可以把比如一个服务消费者(项目)同时启动若干个服务器访问地址呢:
注: 微服务不等于springcloud
服务网关:就是拿着客户端的请求,负载均衡到客户端想要访问请求的服务集群中的某个功能服务器中。
还可以继续分:
也就是说我们上面知道了springcloud基于了springboot实现了微服务的各种功能组件的自动装配,因此我们要遵循下面的版本兼容问题:
第一步:首先把拆分的各个功能模块的服务所用到的数据库准备好:
第二步:导入工程
注意:我们知道springcloud基于了springboot实现了微服务的各种功能组件的自动装配,因此我们要遵循版本兼容问题(上面已经写过):
第三步:将这两个拆分的功能模块服务服务器都启动:
第四步:客户端访问
通过上面的简单演示,这就达成了微服务的原则了,也就是说成功的把订单模块、用户模块拆分成服务(本来这个订单模块。用户模块可以写在同一个项目当中的,比如我们的瑞吉项目里面的功能都写在了一起,现在我们通过微服务把各自功能都拆分开来了,降低了代码的耦合度),互不影响,各自都对应着自己对应的数据库(数据库做到了分离),并且这两个服务都各自有自己的服务器(一个8080,一个8081)这就达到了微服务的目的了。
显然我们要想达到客户的需求,那么我们肯定不能拿着订单模块的用户id直接查询用户模块对应的数据库中对应的数据,因为我们这个订单模块已经和用户模块拆分开了,已经不在同一个数据库当中了所以肯定查询不到了,我们订单模块怎么可能知道用户模块对应的数据库是啥呢,所以这种方式达到不目的。
解决这种需求的做法就是远程调用方式获取:
那么用java代码中如何实现远程调用呢:
用RestTemplate:
第一步:
第二步:
我们知道客户端的需求是:先根据订单id在订单模块功能中查询到订单数据之后,再通过订单中所对应的用户名id向用户模块发送请求获取到相对应的用户名对应的数据。(因此我们可以在订单模块的业务层使用远程调用向用户模块服务发送url请求,获取相对应的数据)、
- package cn.itcast.order.service;
-
- import cn.itcast.order.mapper.OrderMapper;
- import cn.itcast.order.pojo.Order;
- import cn.itcast.order.pojo.User;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.web.client.RestTemplate;
-
- @Service
- @Slf4j
- public class OrderService {
-
- @Autowired
- private OrderMapper orderMapper;
-
- @Autowired
- private RestTemplate restTemplate;
-
- public Order queryOrderById(Long orderId) {
- // 1.查询订单
- Order order = orderMapper.findById(orderId);
-
- log.info("order:"+order);
- // order:Order(id=101, price=699900, name=Apple 苹果 iPhone 12 , num=1, userId=1, user=null)
- // 这个userId 就是该订单对应的用户名id
-
- /**
- * 1、首先我们订单模块服务中查询订单查询出来的数据中有订单相对应的用户名id
- * 因此我们可以先获取到该订单相对应的用户名id
- */
- Long userId = order.getUserId();
-
-
- /**
- * 2、利用RestTemplate向用户模块发送http请求,发送访问用户模块的通过用户名id查询数据的路径,
- * 拿到该用户名id对应的数据 (首先要先注入RestTemplate对象)
- */
- String url ="http://localhost:8081/user/"+userId; // 用户模块中的通过id查询对应用户数据的访问路径地址
- User user = restTemplate.getForObject(url, User.class); // 把通过用户名id查询到的该id对应的数据封装到User实体类当中
-
- log.info("user:"+user); // user:User(id=1, username=柳岩, address=湖南省衡阳市)
-
- order.setUser(user); // 然后将封装到User实体类当中的该用户名id对应的数据封装到order实体类当中
- // 4.返回
- return order; // 最终返回给用户,那么用户就不仅拿到了该订单模块通过id查询出来的数据,并且拿到了该订单相对应的用户名id对应的用户数据了。
- }
- }
注:我们在分析什么是微服务的时候知道,注册中心就是专门用来记录和管理我们拆分的各个微服务(各个功能模块)所在的服务器的ip地址的等其他应用功能。
因此我们怎么解决这个远程调用出现的问题呢:就需要通过eureka注册中心来解决此远程调用出现的问题 (有瑞卡)
具体的代码操作如下所示:
项目创建好之后,那么我们就可以把上面第一步中的依赖引入到项目中了:
然后就是第二步:编写启动类添加注解
第三步:添加application.yml配置文件,编写下面的配置
然后这三步创建好之后,那么这个eureka服务注册中心就创建好了(这个eureka-server项目就是eureka服务注册中心),我们有了有瑞卡注册中心后,等会就可以把服务消费者和服务提供者的服务器访问地址放入到我们有瑞卡注册中心了。
值得知道的一点: 我们创建好上面三步之后,可以启动这个有瑞卡服务:
启动之后,我们可以在页面上访问 localhost:端口号 (这个端口号就是这yml配置文件中配置的有瑞卡服务的端口号):
也就是说我们通过上面的步骤知道了eureka注册中心已经创建好了,那么我们就可以把服务消费者和服务提供者(也就是各功能模块,比如支付功能模块、用户功能模块)的服务器访问地址存放到eureka注册中心去了,这就叫做服务注册。
将user-service服务注册到有瑞卡注册中心:
注:我们上面知道这个user-service服务就是服务提供者。(我们现在把这个服务提供者的服务器访问地址存放到有瑞卡注册中心去)
1、在user-service服务(用户模块功能)项目中导入上面的坐标并且添加配置:
配置好之后,我们就启动这个服务消费者服务即可(要保证启动服务器),然后我们有瑞卡注册中心通过访问地址,就可以查看到好家伙这个服务消费者的服务器访问地址还真的存放到有瑞卡注册中心了:
通过上面的操作,我们在服务提供者项目中也添加导入上面的依赖坐标并且添加yml配置,同理服务提供者的服务器访问地址也可以存放到eureka服务注册中心了:
演示如下所示:
也就是说我们现在eureka服务注册中心中已经存放了服务提供者的服务器访问地址了,那么我们服务消费者就可以在这个eureka服务注册中心中拉取这些存放的服务提供者的服务器访问地址了,拉取到后我们服务消费者就可以指定一个服务提供者的访问地址然后调用其服务提供者的开放接口了,最终就能拿到该服务提供者模块(如支付模块)的功能了,(这样也解决了硬编码问题),这就叫做服务发现。
首先我们要知道:
结果测试:
也就是说我们上面知道了当服务消费者拉取到服务提供者多个服务器访问地址的时候,是会通过负载均衡的方式轮循调用该服务提供者的服务器访问地址的,但是我们只知道是这样我们知道其中的原理吗,那肯定就不知道了,之所以我们服务消费者可以通过负载均衡轮循访问服务提供者的服务器访问地址,那全是Ribbon(肉本)负载均衡起的作用。
随机访问策略:
测试:
也就是说上面的服务消费者第一次发送url请求的时候,会先创建RibbonLoadBanceClient的,然后操作上面圈起来的步骤,因此是比较耗时的,这就是懒加载。
在order-service服务消费者中加入下面的配置,然后当服务消费者第一次发送url的时候,就不会再耗时了。
演示:
我们怎么做到第一次就能让他耗时很短呢,那就需要配置饥饿加载了,配置好饥饿加载后,那么当项目启动的那一刻,那个对象和其他圈起来的操作就已经完成好了,那么第一次再发送url请求的时候就不会再创建那个对象了,因此就不会再耗时那么久了,也就解决了Ribbon第一次发送url的时候懒加载了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。