目录
从其我们学习的都是单体架构,比如苍穹外卖,特点就是将业务的所有功能都集中在一个项目中开发。与之相比较的是分布式架构,根据业务功能对系统进行拆分,每个业务模块作为独立项目开发。
分布式架构要考虑的问题包括:服务拆分粒度如何?服务器集群地址如何维护?服务器之间如何远程调用?服务器健康如何感知?在前人的探索中总结得出了微服务来解决。
微服务是一种经过良好架构设计的分布式架构方案。以下是需要学习的微服务技术栈。
SpringCloud是目前国内额使用最广泛的微服务框架,集成了各种微服务功能组件,并基于SpringBppt实现了这些组件的自动装配,从而提供了良好的开箱即用体验。(需要注意版本匹配的问题)
可以看到现在运行了三个服务:一个订单和二个用户。订单的功能就是查询订单,用户的功能就是查询用户信息。如何在查询订单的同时也将用户信息查到并整合到一起返回呢?
毫无疑问,我们得使用远程调用。思路:在调用订单功能时,要去发起查询用户信息的操作,将查询到的信息之后在订单模块中整合后返回。查询用户信息,意味要发送http请求,如何在java代码中发起http请求呢?
使用RestTemplate。
使用步骤:1.在配置类(启动类也是配置类)中注册RestTemplate。
- @Configuration
-
- public class Configration {
- @Bean
- @LoadBalanced
- public RestTemplate restTemplate(){
- return new RestTemplate();
- }
- }
2.在需要使用远程调用的方法里注入RestTemplate并调用里面的方法发起http请求。
- public Order queryOrderById(Long orderId) {
- // 1.查询订单
- Order order = orderMapper.findById(orderId);
- String url="http://userservice/user/"+order.getUserId();
- User user = restTemplate.getForObject(url, User.class);
- order.setUser(user);
- // 4.返回
- return order;
- }
服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)
服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)
服务既可以时消费者也可以是提供者。
如果我们像之前一样使用硬编码去远程调用会存在问题。第一个问题就是,如果服务实例是多个形成一个集群,每个实例端口号不同,那么怎么去修改硬编码中的url呢?还有url过长的情况要如何解决总不能全写进去吧。
因此使用Eureka注册中心来解决:服务消费者获取服务提供者地址信息,多个服务提供者之间进行负载均衡的选择,得知服务提供者的健康状态。
步骤:需要单独创建一个model,引入spring-cloud-starter-netflix-eureka-server依赖。编写启动类,添加@EnableEurekaServer注解。添加application.yml配置文件。
在配置文件中需要配置:端口、服务名称、eurake的地址(eurake本身也是一个服务)。
- server:
- port: 10086
- spring:
- application:
- name: eurekaserver
- eureka:
- client:
- service-url:
- defaultZone: http://127.0.0.1:10086/eureka
步骤:在项目中导入spring-cloud-starter-netflix-eureka-client依赖。在application.yml配置文件中配置服务名称、eurake地址。
- spring:
- application:
- name: orderservice
- eureka:
- client:
- service-url:
- defaultZone: http://127.0.0.1:10086/eureka
为一个服务启动多个实例可以按如下操作:
在orderService中将url路径用服务名单体ip和端口,并且在order-service项目的配置类中在RestTemplate上添加@LoadBalanced实现负载均衡。
- @Configuration
-
- public class Configration {
- @Bean
- @LoadBalanced
- public RestTemplate restTemplate(){
- return new RestTemplate();
- }
- }
-
-
-
-
-
- public Order queryOrderById(Long orderId) {
- // 1.查询订单
- Order order = orderMapper.findById(orderId);
- String url="http://userservice/user/"+order.getUserId();
- User user = restTemplate.getForObject(url, User.class);
- order.setUser(user);
- // 4.返回
- return order;
- }
-
Eureka底层使用Ribbon实现负载均衡。
LoadBalancerInterceptor继承了 ClientHttpRequestInterceptor,而它会拦截http请求。它的实现类中重现了方法。大致就是获得url,等到url里面的服务名,如果不为空则去执行。执行的第一步就是获得服务列表,然后在负载均衡。
负载均衡策略常见的如下
方法一:在配置类中定义一个新的IRule。
-
- @Bean
- public IRule randomRule(){
- return new RandomRule();
- }
方法二:针对某个服务可以在该配置文件中,添加配置达到修改的目的。
- userservice:
- ribbon:
- NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:
- ribbon:
- eager-load:
- enabled: true
- clients:
- - userservice
Nacos是阿里巴巴的产品。现在是SpringCloud中的一个组件。相比Eureka功能更加丰富,在国内受欢迎程度较高。
步骤:在父工程中添加spring-cloud-alibab的管理依赖
- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-alibaba-dependenciesartifactId>
- <version>2.2.5.RELEASEversion>
- <type>pomtype>
- <scope>importscope>
- dependency>
注释掉原先eureka依赖
添加nacos的客户端依赖
- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
- dependency>
修改user-service和order-service中的application.yml文件,注释掉eureka地址,添加nacos地址
- spring:
- cloud:
- nacos:
- server-addr: localhost:8848
可以将多个实例按地区划分分成不同的集群。因此,结构由原先的两级变成三级:服务、集群、实例。
配置集群需要在配置文件中添加如下:
- discovery:
- cluster-name: BJ
在服务消费者也配置集群的,并设置负载均衡的IRule为NacosRule,这个规则优先会寻找与自己同集群的服务,在本集群中再随机,如果本集群无服务回去请求其他集群。
- userservice:
- ribbon:
- NFloadBalancerRuleClassName:
Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高。在nacos的网页上对其进行修改。权重一般是0-1,越小的话,访问频率越低。这里提供了平滑更新的可能,将需要更新的服务,权重降低,更新完后权重再升高,不至于更新的时候整个服务不能访问。
Nacos中服务存储和数据存储的最外层都是一个名为namespace的东西,用来做最外层隔离。(非强制)
创建命名空间如下
修改命名空间需要在配置文件application.yml下配置namespace并填写上命名空间的ID。
命名空间不同,不能访问对方。
本笔记是学习黑马的SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式.....课程学习,目前感受还挺好的,如果有什么不好理解的,大家也可以去看看视频~