【进阶】微服务
- 互联网
- 2025-08-31 13:24:01

微服务架构 服务架构演变过程 单体应用架构
所有的功能都在一个项目中(现在使用的就是单体架构)
集群架构把一个单体项目部署多个,使用Nginx进行负载均衡,根据负载均衡策略调用后端服务
不好的地方:有的服务访问量大,有的服务访问量小,这样不管访问量大小,都会进行多次部署。
垂直架构将不同功能模块进行拆分,服务之间可以相互调用,还可以根据访问量大小进行选择性的多次部署。
不好的地方:服务之间的管理调用比较麻烦
微服务架构微服务就提供了一套完成的,对多个服务进行管理的解决方案
服务治理(管理这么多服务)
服务调用
服务网关(对外提供一个统一的入口)
链路追踪
常见的微服务解决方案
原生的SpringCloud
本次使用springCloud alibaba 是阿里巴巴开源的一套微服务解决方案
微服务案例以电商为例
订单服务
商品服务
用户服务
以下订单为例,在订单服务中欧调用商品服务,用户服务
简单演示服务调用
restTemplate.getForObject(url,类.class); 服务管理服务注册中心,将微服务中的多个服务管理起来
常见的注册中心
Zookeeper:
Eureka:
Nacos:是springcloud alibaba中使用的
nacos是一个注册中心,用来管理服务,
安装
启动,
在项目中配置一个服务名,
再配置一个注册中的地址
服务调用版本1: restTemplate.getForObject("http://127.0.0.1:8094/product/get/"+pid, Product.class);//弊端ip,端口写死的, 如果有多个服务使用不方便 , 没有用到注册中心
版本2: 使用naocs提供的客户端DiscoveryClient,动态从注册中心 通过服务名 获取服务,使用到了注册中心
List<ServiceInstance> instances = discoveryClient.getInstances("service-product"); ServiceInstance productService = instances.get(new Random().nextInt(instances.size()));//从商品服务中随机获取一个服务 String productUrl = productService.getHost()+":"+productService.getPort();//动态获取服务ip和服务端口 Product product = restTemplate.getForObject("http://"+productUrl+"/product/get/"+pid,Product.class);版本3: 使用Ribbon组件实现负载均衡功能
restTemplate.getForObject("http://服务名/product/get/"+pid,Product.class); ribbon: ConnectTimeout: 2000 # 请求连接的超时时间 ReadTimeout: 5000 # 请求处理的超时时间 service-product: # 调用的提供者的名称 ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule 负载均衡策略版本4: 使用Feign组件,可以将访问地址与接口绑定, 这样我们就可以像调用本地服务一样,取调用别的服务
版本4: 使用Feign组件,可以将访问地址与接口绑定, 这样我们就可以像调用本地服务一样,取调用别的服务
@FeignClient(value = "service-product") //服务名 public interface ProductService { @GetMapping(path = "/product/get/{id}")//接口地址 Product findProductById(@PathVariable("id")int id); } @Autowired ProductService productService; Product product = productService.findProductById(pid); 服务容错高并发场景下,如果访问量过大, 不加以控制,大量的请求堆积,会击垮整个服务.
需要在某些场景下,为了保证服务不宕机.
使用jmeter测试工具, 模拟多线程 向后端服务发起请求
要对请求进行限制
使用Sentinel组件对请求进行各种控制
1.在项目中做一些配置
2.启动sentinel可视化客户端 在客户端中配置流控规则
java -Dserver.port=9999 -Dcsp.sentinel.dashboard.server=localhost:9999 -jar sentinel-dashboard-1.8.5.jar 网关网关是为众多的微服务提供一个统一的访问入口.
所有请求先进入到网关,可以在网关中进行一些全局处理,例如权限验证,token验证,限流.
网关搭建
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <scope>test</scope><!--打包运行时,就会剔除掉jar--> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> <scope>test</scope> </dependency>在网关中做两件事情:
1.搭建全局过滤器
2.在网关中进行限流
消息队列消息队列(Message Queue) 缩写为MQ
消息队列一般也称为消息队列中间件
中间件: 例如tomcat,redis都可以称为中间件, 是可以实现两个不同内容之间进行交互的软件
消息队列的使用场景
异步解耦
将一些不需要即时响应的操作放到消息队列中,
例如在项目中发送短信验证码,邮箱验证码,
可以在点击发送后,先将要发送的内容放入到消息队列中,然后给用户做出响应,
之后发送邮件或者发送短信的服务从消息队列中取出要发送的信息逐一处理即可.
实现了从同步发送消息 变为 异步发送消息
以RocketMQ为例
安装(略)
测试
NameServer(邮局) 消息队列的协调者,消息队列的总服务
Broker(邮递员) 负责发送,存储,投递消息
Producer(寄件人) 消息的生产者
Consumer(收件人) 消息的消费者
Topic(地区) 用来区分不同类型的消息,可以给不同的消息定义主题,用来区分不同类型消息
Message Queue(邮件) 发送的消息内容
分布式锁在微服务系统中,一个项目可以有多个服务(进程),
此时java中的锁例如synchronized锁就会失效。
使用分布锁来对多个进程中操作进行控制
如何实现分布式锁:
基于redis实现分布式锁,在redis中可以存储一个变量,用来当做锁标志,因为redis是共享的.
例如,redis中存在共享变量,说明有用户正在操作,持有锁, 用完之后删除变量,就是释放了锁.
redis中的有一个setnx命令,在向redis中设置值的时候,会自动判断redis中是否存在指定的key,
如果redis中不存在,就设置成功(相当于获取锁成功)
如果redis中存在,就设置失败(相当于获取锁失败)