> 文章列表 > SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈(Eureka、Ribbon)

SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈(Eureka、Ribbon)

SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈(Eureka、Ribbon)

微服务技术栈导学

微服务技术是分布式架构(把服务做拆分)的一种

而springcloud仅仅是解决了拆分时的微服务治理的问题,其他更复杂的问题并没有给出解决方案

一个完整的微服务技术要包含的不仅仅是springcloud

微服务技术栈

包括什么
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

认识微服务

(一)服务架构演变

1、单体架构

在这里插入图片描述

2、分布式架构

在这里插入图片描述

3、服务治理

在拆分的过程中也会有一些问题
在这里插入图片描述

4、微服务

在这里插入图片描述

5、总结

在这里插入图片描述

(二)微服务技术对比

1、微服务结构

在这里插入图片描述

2、微服务技术对比

在这里插入图片描述
SpringCloudAlibaba兼容了前面两种

3、企业需求

在这里插入图片描述

(三)SpringCloud

在这里插入图片描述
在这里插入图片描述

服务拆分

(一)案例Demo

1、服务拆分注意事项

在这里插入图片描述

2、导入服务拆分Demo

在这里插入图片描述
在这里插入图片描述
order表user_id虽然和user表进行关联,但是因为是跨database的,因此无法进行关联查询

在这里插入图片描述
项目中所有的微服务:
在这里插入图片描述
以下是两个分别的application.yml

server:port: 8080
spring:datasource:url: jdbc:mysql://localhost:3306/cloud_order?useSSL=falseusername: rootpassword: root123456driver-class-name: com.mysql.jdbc.Driver
mybatis:type-aliases-package: cn.itcast.user.pojoconfiguration:map-underscore-to-camel-case: true
logging:level:cn.itcast: debugpattern:dateformat: MM-dd HH:mm:ss:SSS
server:port: 8081
spring:datasource:url: jdbc:mysql://localhost:3306/cloud_user?useSSL=falseusername: rootpassword: root123456driver-class-name: com.mysql.jdbc.Driver
mybatis:type-aliases-package: cn.itcast.user.pojoconfiguration:map-underscore-to-camel-case: true
logging:level:cn.itcast: debugpattern:dateformat: MM-dd HH:mm:ss:SSS

将两个都启动:
在这里插入图片描述
在浏览器中(下载Chrome插件Json Viewer)
在这里插入图片描述
在这里插入图片描述

(二)服务远程调用

1、根据订单id查询订单功能

在这里插入图片描述

2、远程调用方式分析

那么问题就转变成了:如何在java代码中(像浏览器一样)发起http请求,这样就能实现远程调用了
在这里插入图片描述
Spring提供了一个工具——RestTemplate,用来发http请求
在这里插入图片描述

通过Bean的方式把RestTemplate注册为其中的一个对象,然后将来可以在任何地方注入这个对象来使用

写在哪里呢?Bean的注入只能放在配置类中,而启动类(OrderApplication)(带有@SpringBootApplication)本身也是配置类,所以完全可以在这里写Bean的注入

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}/* 创建RestTemplate并注入Spring容器* @return*/@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}

接下来就可以利用它来发http请求了
在这里插入图片描述

修改OrderService

@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;// 0.注入RestTemplate@Autowiredprivate RestTemplate restTemplate;public Order queryOrderById(Long orderId) {// 1.查询订单Order order = orderMapper.findById(orderId);// 2.利用RestTemplate发送http请求,查询用户// 2.1.url路径String url = "http://localhost:8081/user/" + order.getUserId();// 2.2.发送http请求,实现远程调用(getForObject默认返回json,加上User.class参数g告诉它返回值的类型,自动转化成User对象)User user = restTemplate.getForObject(url, User.class);// 3.封装user到Orderorder.setUser(user);// 4.返回return order;}
}

然后重启Order服务(User服务就不需要重启了)
在这里插入图片描述

3、总结

在这里插入图片描述

Eureka注册中心

(一)提供者与消费者

在这里插入图片描述

(二)eureka原理分析

1、服务调用出现的问题

在这里插入图片描述

刚才将user-service服务的ip和端口硬编码在代码中的,有一定问题
所以不能用硬编码方式

在这里插入图片描述

2、Eureka的作用

在这里插入图片描述

每一个服务启动时都会把自己的信息注册给eureka

如果某个心脏不跳动了,eureka会将这个从列表中删除
在这里插入图片描述

3、总结

在这里插入图片描述

(三)搭建eureka服务

1、动手实践

在这里插入图片描述

2、搭建EurekaServer

在这里插入图片描述

搭建EurekaServer需要创建一个独立的微服务

starter是springboot中的自动装配,也就是说在这个依赖中已经帮我们把springeureka的所有的配置都做好了,也就是说我们可以零配置直接拿来用了

当然,自动装配是需要有开关的,第二步这个注解就是eurekaserver自动装配的开关

第三步需要编写一些配置信息,端口信息、服务名称、eureka的地址信息

接下来开始写:
1、创建一个新的module
在这里插入图片描述
引入依赖:

<dependencies><!--eureka服务端--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency>
</dependencies>

注意到我们引入的时候并没有指定版本信息,以前学习springboot时也遇到过这种情况,原因是在我们的父工程中,已经把依赖的版本都管理好了,所以可以进入cloud-demo的父工程的pom文件看,可以看到spring-boot-starter-parent的版本为2.3.9.RELEASE,以及spring-cloud版本和其他,并且有spring-cloud-dependencies依赖库,里面有大量的springcloud的组件及其版本信息,全都定义好了,所以在我们引入springcloud组件时,我们无需指定任何版本信息

2、编写main函数并添加注解
新建cn.itcast.eureka.EurekaApplication类

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class, args);}
}

3、编写一个配置文件
resources下新建application.yml

server:port: 10086 # 服务端口
spring:application:name: eurekaserver # eureka的服务名称
eureka:client:service-url: # eureka的地址信息defaultZone: http://127.0.0.1:10086/eureka

注意由于eureka自己也是一个微服务,会将自己也注册到eureka上(这是为了将来eureka集群去用的),所以它也需要一个名字,而且还需要再配一个eureka的地址eureka.client.service-url

也就是说“这里是为了做服务注册才配置这些信息”

然后点击EurekaApplication左边的三角形启动,就可以在下面的服务中看到多出来了EurekaApplication
在这里插入图片描述
点击这个蓝色的端口号,会自动跳转到浏览器

点击10086,就跳转到了eureka的管理界面
在这里插入图片描述

status中的up表示正常状态,down表示挂掉了,up后面的是ip

(四)服务注册

1、注册user-service

在这里插入图片描述
可以看到,除了依赖不一样(刚才时eureka的服务端,现在是eureka的客户端),这个配置和刚才在eureka中做的配置文件长得非常像。为什么?因为eureka启动时会把自己注册到eureka,所以它也需要配服务名称和地址。所以服务名称和地址的配置实际上是服务注册的配置,只要配了它,就可以做注册

<!--eureka客户端依赖-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

然后配置yml文件

server:port: 8081
spring:datasource:url: jdbc:mysql://localhost:3306/cloud_user?useSSL=falseusername: rootpassword: root123456driver-class-name: com.mysql.jdbc.Driverapplication:name: userservice # user服务的服务名称
mybatis:type-aliases-package: cn.itcast.user.pojoconfiguration:map-underscore-to-camel-case: true
logging:level:cn.itcast: debugpattern:dateformat: MM-dd HH:mm:ss:SSS
eureka:client:service-url: # eureka的地址信息defaultZone: http://127.0.0.1:10086/eureka

然后重启UserApplication

接下来把Order服务也注册到Eureka,同上,然后重启
在这里插入图片描述
这里每个服务都只有一个实例,我们可以每个服务启动多个实例

在这里插入图片描述
在这里插入图片描述
(在这里配置端口,是为了覆盖yml文件的端口的)在这里插入图片描述
然后把它也启动,
在这里插入图片描述

(五)服务发现

我们希望orderservice可以基于服务名称拉取到userservice的两个实例信息,然后实现负载均衡
在这里插入图片描述
用服务名称代替ip、端口:在eureka中可以看到userservice这个服务名代指的就是这两个端口

要在多个实例中负载均衡,要给之前用到的RestTemplate这个Bean加一个注解@LoadBalanced

都弄完之后,我们把两个UserApplication的都清空,因为我们想知道OrderApplication究竟使用的是哪一个UserApplication,因为在OrderService中url中只是userservice,没有加任何ip地址

(六)总结

在这里插入图片描述

Ribbon负载均衡

(一)负载均衡原理

在这里插入图片描述
直接在浏览器中访问userservice/user/1是无法访问的

在这里插入图片描述

(二)负载均衡策略

IRule接口决定了负载均衡的策略
在这里插入图片描述
在这里插入图片描述
ZoneAvoidanceRule是默认

在这里插入图片描述
注意第一种代码方式是全局的,也就是说我一旦配了上面这种方案,在orderservice中不管你是调用哪一个微服务,都是randomrule;而第二种配置文件方式会先指定服务名称,再指定负载均衡的规则,只针对某个服务而言。

(三)饥饿加载

重启OrderApplication,
在这里插入图片描述
达到了非常恐怖的311毫秒,然后再刷新一次,
在这里插入图片描述
时长就只有19毫秒了

在这里插入图片描述

创建LoadBalanceClient的过程中还要做服务的拉取,因此时间长

(这个配置是在orderservice的application.yml文件)

server:port: 8080
spring:datasource:url: jdbc:mysql://localhost:3306/cloud_order?useSSL=falseusername: rootpassword: root123456driver-class-name: com.mysql.jdbc.Driverapplication:name: orderservice # order服务的服务名称
mybatis:type-aliases-package: cn.itcast.user.pojoconfiguration:map-underscore-to-camel-case: true
logging:level:cn.itcast: debugpattern:dateformat: MM-dd HH:mm:ss:SSS
eureka:client:service-url: # eureka的地址信息defaultZone: http://127.0.0.1:10086/eureka
userservice:ribbon:NFLoadBalanceRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
ribbon:eager-load: enabled: true # 开启饥饿加载clients: # 指定饥饿加载的服务名称- userservice- xxservice

这个ribbon与上面userservice下的ribbon不冲突

(四)总结

在这里插入图片描述