简介
Spring Cloud Alibaba中文官方地址网址打不开的话可以用手机QQ浏览器。
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案
。此项目包含开发分布式应用 微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布 式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置
,就可以将 Spring Cloud 应用 接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。 https://github.com/alibaba/spring-cloud-alibaba
Spring Cloud Alibaba的优劣势
SpringCloud 的几大痛点
- SpringCloud 部分组件(Eureka)停止维护和更新,给开发带来不便;
- SpringCloud 部分环境搭建复杂,没有完善的可视化界面,我们需要大量的二次开发和定制
- SpringCloud 配置复杂,难以上手,部分配置差别难以区分和合理应用
SpringCloud Alibaba 的优势:
阿里使用过的组件经历了考验,性能强悍,设计合理,现在开源出来大家用 成套的产品搭配完善的可视化界面给开发运维带来极大的便利 搭建简单,学习曲线低。
结合 SpringCloud Alibaba 我们最终的技术搭配方案:
- SpringCloud Alibaba - Nacos:注册中心(服务发现/注册)
- SpringCloud Alibaba - Nacos:配置中心(动态配置管理)
- SpringCloud - Ribbon:负载均衡
- SpringCloud - Feign:声明式 HTTP 客户端(调用远程服务)
- SpringCloud Alibaba - Sentinel:服务容错(限流、降级、熔断)
- SpringCloud - Gateway:API 网关(webflux 编程模式)
- SpringCloud - Sleuth:调用链监控
- SpringCloud Alibaba - Seata:原 Fescar,即分布式事务解决方案
SpringCloud Alibaba - Nacos Discovery服务注册和发现
SpringCloud Alibaba - Nacos官方地址
添加依赖
因为所有服务都需要服务注册/发现,配置中心,所以依赖只需要添加在gulistore-commen模块
<!-- 服务发现/注册中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 配置中心来做配置管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- dependencyManagement 版本控制,
以后再引入spring-cloud-alibaba-dependencies 相关依赖就不需要指定版本了 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
下载windows nacos-server
上面的官方网址有下载地址,版本为1.1.3
配置文件application.yml
spring:
datasource:
username: root
password: root
url: jdbc:mysql://192.168.56.10:3306/gulistore_sms
driver-class-name: com.mysql.jdbc.Driver
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
# 注册中心需要
application:
name: gulistore-coupon
# classpath* 依赖的依赖也扫描
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
# 主键自增
global-config:
db-config:
id-type: auto
server:
port: 7000
开启服务注册发现的客户端
在启动类添加 @EnableDiscoveryClient
查看注册好的服务
地址是 127.0.0.1:8848/nacos 账密都是nacos
SpringCloud - Feign
Feign 是一个声明式的 HTTP 客户端
,它的目的就是让远程调用更加简单。
Feign 整合了 Ribbon(负载均衡)和 Hystrix(服务熔断)
(我们不用这个),可以让我们不再需要显式地使用这 两个组件。
SpringCloudFeign 在 NetflixFeign 的基础上扩展了对 SpringMVC 注解的支持,在其实现下,我 们只需创建一个接口并用注解的方式来配置它,即可完成对服务提供方的接口绑定。
远程调用步骤
- 引入依赖
实际上,我们在创建各微服务模块的时候就已经引入了openFeign依赖了
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 由于SpringCloud Feign高版本不使用Ribbon而是使用spring-cloud-loadbalancer,
所以需要引用spring-cloud-loadbalancer或者降版本-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
- 编写一个接口,告诉SpringCloud,这个接口需要调用远程服务
package com.atguigu.gulistore.member.feign;
import com.atguigu.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
// 需要远程调用的微服务名
@FeignClient("gulistore-coupon")
public interface CouponFeignService {
// 如果调用的方法有@RequestBody等注解的话,这儿要保持高度一致
@RequestMapping("/coupon/coupon/member/list")
public R membercoupons();
}
- 开启远程调用功能
package com.atguigu.gulistore.member;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@MapperScan("com.atguigu.gulistore.member.dao")
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.atguigu.gulistore.member.feign")
public class GulistoreMemberApplication {
public static void main(String[] args) {
SpringApplication.run(GulistoreMemberApplication.class, args);
}
}
SpringCloud Alibaba - Nacos Config配置中心
之前我们把配置放在application.properties配置文件中,如果需要修改的话,还需要打包,部署,这对于已经上线的服务很麻烦
<!-- 配置中心来做配置管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
bootstrap.properties
优先于application.properties加载
bootstrap.application
spring.application.name=gulistore-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
在公共工程添加spring-cloud-starter-bootstrap依赖
spring-boot 2.4版本之后不添加这个依赖,读取不到bootstrap配置文件(application或者yml)
,我用的是2.5.5
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.4</version>
</dependency>
在nacos配置中心添加一个数据集
默认是应用名.properties
gulistore-coupon.properties
测试
package com.atguigu.gulistore.coupon.controller;
import java.util.Arrays;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.atguigu.gulistore.coupon.entity.CouponEntity;
import com.atguigu.gulistore.coupon.service.CouponService;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.R;
/**
* 优惠券信息
*
* @author lx
* @email qazokmzjl@gmail.com
* @date 2021-10-07 17:34:49
*/
// 不加该注解,修改nacos配置文件信息的时候不会自动刷新
@RefreshScope
@RestController
@RequestMapping("coupon/coupon")
//@PropertySource(value= {"classpath:application.yml"},encoding = "utf-8")
public class CouponController {
@Autowired
private CouponService couponService;
@Value("${coupon.username}")
private String name;
@Value("${coupon.age}")
private Integer age;
@RequestMapping("/test")
public R test(){
return R.ok().put("name",name).put("age",age);
}
进阶
Nacos支持“Namespace+group+data ID”的配置解决方案。
命名空间
作用:配置隔离
默认:public(保留空间):新增的所有空间默认都在public。
- 基于环境进行隔离,开发、测试、生产等
bootstrap.properties配置命名空间的id
spring.cloud.nacos.config.namespace = 6c33d81b-dfbf-464c-a992-633db3c40666
-
基于服务进行隔离
每一个微服务之间互相隔离,每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置
bootstrap.properties
spring.cloud.nacos.config.namespace = 9fa73164-2dc0-429c-b5ce-b90ab6a6f482
配置分组
例如双十一用一个配置,平常用一个配置
bootstrap.properties
spring.cloud.nacos.config.group=shaungshiyi
谷粒商城使用的方式
每个微服务创建自己的命名空间,使用配置分组区分环境,dev,test,prod
同时加载多个配置集
随着业务不断的壮大,微服务可能会有非常多的配置,我们不应该将所有的配置全部都写在一个配置文件中,这样配置文件中的配置又多又乱,不好维护。
一般的做法是拆分成不同的配置文件。例如将数据源、框架、微服务等等配置拆分
以前SpringBoot任何方法从配置文件获取值的方式,同样适用。
@Value
@ConfigurationProperties
nacos配置中心(默认为DEFAULT_GROUP)有的优先使用配置中心的,配置中心没有的才会使用我们自定义配置文件中的
在开发阶段为了方便,配置可以写在配置文件中,一旦上线,所有配置都将写在配置中心。此时将只剩一个bootstrap.properties文件
- bootstrap.properties
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=0e5bae64-6ff2-4591-8d3a-8c24760015ba
# 指定配置文件的时候需要用到
#spring.cloud.nacos.config.group=
# 引用多个配置文件
spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml
spring.cloud.nacos.config.ext-config[0].group=dev
spring.cloud.nacos.config.ext-config[0].refresh=true
spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml
spring.cloud.nacos.config.ext-config[1].group=dev
spring.cloud.nacos.config.ext-config[1].refresh=true
spring.cloud.nacos.config.ext-config[2].data-id=other.yml
spring.cloud.nacos.config.ext-config[2].group=dev
spring.cloud.nacos.config.ext-config[2].refresh=true
- 配置中心
SpringCloud - Gateway
简介
网关作为流量的入口,常用功能包括路由转发、权限校验、限流控制等。
而SpringCloud Gateway 作为SpringCloud官方推出的第二代网关框架,取代了zuul网关。
网关不是使用tomcat做的,而是Netty,Netty具有非常高的网络性能。
术语
- route:路由,发一个请求给网关,网关路由到指定的服务或地址
它包括一个标识性的id和目的地的uri
,断言
(断言为真路由就可以匹配,也就是条件判断)的集合,和过滤器
的集合 - predicate(断言):其实是java8的断言函数,网关的断言是允许开发人员匹配
当次请求的任何信息,例如请求头或者请求参数
- filter(路由过滤器):请求或响应之前都可以进行过滤,然后处理。
工作流程
- gateway 接收到前端发送的请求之后通过查看handler mapping(映射信息)能否被路由或者被处理
- 如果可以处理,就交给handler处理器,处理器处理这些请求的话就会经过一系列的filter,当处理器结束以后,就会把这个请求路由给指定的服务
- 指定服务处理完后还经过这一系列filter,返回给前端
总结:请求到达网关,网关利用断言来判断该请求是否符合某个路由规则,如果符合就按照路由规则,经过一系列的filter,路由到指定的地址
创建gateway模块,在启动类添加
// 因为我们的网关模块依然依赖common,而common有mybatis的依赖
// 就会加载数据源
// 排除数据源,网关不需要数据源
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
application.yml
spring:
cloud:
gateway:
routes:
- id: test_route
uri: https://www.baidu.com
predicates:
# 根据参数来匹配
- Query=url,baidu
# 和admin_route顺序不能乱,否则页面访问报404,因为被它拦截了
# 我们一般把精确的路由放在上面,优先级高
# 匹配了这个路由之后,不会匹配下面的路由
- id: product_route
uri: lb://gulimall-product
predicates:
- Path=/api/product/**
# 前端的请求是 http://localhost:88/api/product/category/list/tree
# 后端实际需要的请求是,http://localhost:12000/product/category/list/tree
filters:
- RewritePath=/api/(?<segment>.*),/$\{segment}
# 前端项目发送请求都以 /api 开头
- id: admin_route
# lb 负载均衡 到renren-fast服务
uri: lb://renren-fast
# 匹配所有以api开头的请求
predicates:
- Path=/api/**
filters:
# 路径重写
# http://localhost:88/api/captcha.jpg 在网关匹配到相应的规则后
# 就变成了 http://localhost:8080/api/captcha.jpg
# 但实际上我们需要真正访问的是 http://localhost:8080/renren-fast/captcha.jpg
# (?<segment>.*) $\{segment} 相当于片段
- RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment}
# todo 好多路由规则,单独弄一篇文章不值得,以后有遇到新的,就在这儿添加吧
尚硅谷学习视频B站链接:
https://www.bilibili.com/video/BV1np4y1C7Yf?p=3
而李国华只看见大开本故事书啪地夹起来的时候,夹出了风,掀开了思琪的刘海。他知道小女生的刘海比裙子还不能掀。
房思琪的初恋乐园
林奕含