SpringCloud十大组件使用方法讲解
前言:本文为原创 若有错误的观点欢迎评论!一.注册中心1.依赖:IDEA在Spring Initlizar中选 Spring Cloud Discovery -> Eureka Server2.配置文件:server:port: 8761eureka:instance:hostname: localhostclient:#声明自己是个服务端...
前言:本文为原创 若有错误欢迎评论!
准备工作
1.新建一个空的maven项目
2.在pom文件中
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<!--要注意springboot的版本要和springcloud对应-->
<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--指定编译时的java版本-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<compilerVersion>${java.version}</compilerVersion>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
<!-- prevents endPosTable exception for maven compile -->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
</plugins>
</build>
- 查看版本匹配:https://start.spring.io/actuator/info
3.下面说的每个部分都是在新建一个这个moudle的子模块
一.注册中心
1.依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--必须用web启动器 不然会报错-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.配置文件:
server:
port: 8761
spring:
application:
name: ...
eureka:
instance:
hostname: localhost
client:
#声明自己是个服务端
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
#是否开启自我保护模式,默认为true(开启后因为网络分区故障 微服务本身其实是健康的,此时本不会注销这个微服务)
enable-self-preservation: true
#eureka server清理无效节点的时间间隔,默认60000毫秒,即60秒
eviction-interval-timer-in-ms: 10000
3.在启动类注解:
@EnableEurekaServer
二.注册服务
1.依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.配置文件:
server:
port: 877?
eureka:
client:
serviceUrl:
#注册中心地址(必须设置
defaultZone: http://localhost:8761/eureka/
#去注册中心注册的最长时间(可以不设置用默认的)
registry-fetch-interval-seconds: 5
instance:
#心跳时间(可以不设置用默认的)
lease-renewal-interval-in-seconds: 5
#过期时间(可以不设置用默认的)
lease-expiration-duration-in-seconds: 15
#服务的名称
spring:
application:
name: ???
4.在启动类注解
@EnableDiscoveryClient
三.调用方式ribbon
1.依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
2.在启动类增加:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
3.使用:
@Autowrid
private RestTemplate restTemplate;
Object obj=restTemplate.getForObject("http://注册过的服务名/?/?/ ? = ", .class)
四.调用方式fegin
1.依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.在启动类注解
@EnableFeginClients
3.使用:
-
创建一个interface 并注解 (该注解会使自动注入spring容器 就不用再加@Component注解)
@FeginClient(name=“注册过的服务名”)
-
在该接口中要写方法 返回值和提供者controller中对应方法返回值相同 但也可以是提供者方法返回值的一部分 并给方法注解
@RquestMapping(value=“被注解服务要调用的controller的类的路由/方法的路由”,method=“GET”)
-
方法的参数 : @RequestParam(value=“被调用服务方法的参数名”)
@GetMapping("/api/v1/find")
String findById(@RequestParam(value=“id”) int id)
- 注意
- 参数的类型和参数名一定要和别调用服务的方法的参数类型相同
- RequestParam 里必须给 value 属性赋值
- 如果是提供服务的方法返回的对象 但调用者的返回参数的是String类型 则返回的是目标对象的json字符串 用JsonNode obj=ObjectMapper.readTree(str)得对象
- 在要使用请求会的目标的类注入上个interface
@Autowrid
private …FeginClient feginclient; //@FeginClient注解会使注入spring容器
- 注意:
- 路径
- Http方法必须对应(即:请求方式、参数类型、参数名必须相同)
- 当被调用服务的方法参数为用@RequestBody注解时,调用方应该使用@PostMapping
- @RequestParam 里的 value 属性必须赋值
4.超时配置
#修改调用超时时间
feign:
client:
config:
default:
connectTimeout: 2000
readTimeout: 2000
5.如果用@FeginClient对此注解同一个被调用的服务在springboot>2.1时 会报多次注入同一个bean的错误 需要加
spring:
main:
allow-bean-definition-overriding: true
7.ribbon和feign的选择
-
选择feign
- 默认集成了ribbon
- 写起来更加思路清晰和方便
- 采用注解方式进行配置,配置熔断等方式方便
-
使用fegin的正确姿势
- 在服务提供者建立一个对外提供服务的moudle 该moudle里有
1)、服务提供者的实体类(不然返回对象时只有返回json字符串 然后被调用者去解析json字符串)
2)、对外提供api的多个接口 每个接口对应一个controller类 并且保证类上的@RequestMappeing路径、方法上的路由、方法的参数与接口一致 - 在服务调用者依赖提供者对外提供服务的moudle 然后新建多个接口分别继承每个接口 并给继承后接口注解@FeginClient(“服务名”) 之后这个就可以通过这个接口调用提供者的方法
(如果不这样做那么每个服务的调用者都要知道并且写一遍提供方的:路由、方法名、方法参数)
- 在服务提供者建立一个对外提供服务的moudle 该moudle里有
-
注意:微服务的每个entiyty实体类都要 implements Serializable
五.Hystrix断路器
1.依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.启动类注解:
@EnableCircuitBreaker
3.使用
-
在要调用服务的最外层(即controller层)方法上加注解
@HystrixCommand(failbackMethod=“失败时调用的方法名”)
-
实现失败时调用的方法(注意参数要与被调用服务的方法包括参数名完全一致)
4.Fegin请求时的熔断机制:
-
执行完3的全部
-
开启feign支持hystrix (旧版本默认支持,新版本默认关闭)
feign: hystrix: enabled: true
-
给fegin的接口加注解
@FeginClient(name=" ",fallback=?.class)
-
建一个失败回调类(名字和failback的名字相同) 注解spring、继承Fegin的接口
请求其他服务失败时
第一次降级:每个被继承的方 在方法体里写的代码
第二次降级:执行Fegin是实现类的代码会跳出到执行最外层controller 继续降级 执行failbackMethod -
监控报警机制:
使用redis缓存(为了获得标识位)
从redis中取值 判断是否为空
开启一个子线程
给redis存值与失效时间
进行发短信等预警操作//监控报警 String saveOrderKye = "save-order"; String sendValue = redisTemplate.opsForValue().get(saveOrderKye); final String ip = request.getRemoteAddr(); new Thread( ()->{ if (StringUtils.isBlank(sendValue)) { System.out.println("紧急短信,用户下单失败,请离开查找原因,ip地址是="+ip); //发送一个http请求,调用短信服务 TODO redisTemplate.opsForValue().set(saveOrderKye, "save-order-fail", 20, TimeUnit.SECONDS); }else{ System.out.println("已经发送过短信,20秒内不重复发送"); } }).start();
6.超时时间
hystrix引入之后配置超时时间还需要加一个:
feign:
client:
config:
default:
connectTimeout: 2000
readTimeout: 2000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 4000
注意:和fegin集成ribben的超时时间 两个一起才生效
六.网关
1.依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!--注意:还要引入Eureka Discovery来注册-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.配置文件:
- 端口号
- 应用名
- 在Erueka注册
3.在启动类注解
@EnableZuulProxy
注意:@EnableZuulProxy默认集成了@EnableCircuitBreaker
4.设置路径
- 服务路由映射
zuul: routes: order-service: /apigateway/**
- 忽略整个服务
zuul: ignored-service: order-service
- 忽略路径
zuul: ignored-patterns: /*-service/**
4.示例
zuul:
routes:
login:
path: /login
serviceId: shared-parking-mange-auth
#是否携带前缀 默认true为不带
stripPrefix: false
auth:
path: /auth/**
serviceId: shared-parking-mange-auth
#是否携带前缀 如果不带请求路径是对应微服务的auth后 /**
stripPrefix: false
user:
path: /user/**
serviceId: shared-parking-mange-user-service
stripPrefix: false
#微服务要设置cookie就必须携带host
add-host-header: true
#覆盖默认敏感头信息,将其设置为空就可以,不然像 Set-Cookie...这类respone的header无法返回
sensitive-headers:
5.自定义过滤器
-
新建一个类 并注解【@Component】注入
-
如何获取HttpServletRequest
RequestContext context=RequestContext.getCurrentContext(); HttpServletRequest request=context.getRequest();
-
extend ZuulFilter 重写四个方法
-
在shouldFilter() 里拿到请求的相对路径然后判断是否拦截(如果项目大放在拦截路径放在redis中)
-
在run()中 对要拦截的路径进行校验(推荐使用JWT加密算法 可以避免数据库查询)
-
校验不通过
requestContext.setSendZuulResponse(false) requestContext.setResponseStatusCode(HttpStatus.?.value());
-
run()方法通不通过都return null
@Component /** * 注入读取配置文件的实体类:JwtProperties(jwt相关配置)、FilterPropertiess(要拦截的路径) * jwt不会的话参考我的:https://blog.csdn.net/weixin_43934607/article/details/101356581 * * jwt: * pubKeyPath: C:\\tmp\\rsa\\rsa.pub # 公钥地址 * cookieName: SHOP_TOKEN # cookie的名称 * filter: * allowPaths: * - /api/auth * - /api/search * - /api/user/register * - /api/user/check * - /api/user/code * - /api/item */ @EnableConfigurationProperties({JwtProperties.class, FilterPropertiess.class}) @Component public class LoginFilter extends ZuulFilter { @Autowired private JwtProperties jwtProperties; @Autowired private FilterPropertiess filterPropertiess; //过滤器类型 一般用pre 最先拦截 @Override public String filterType() { return "pre"; } //顺序 值越大越靠前 @Override public int filterOrder() { return 10; } @Override public boolean shouldFilter() { //获取要拦截的路径 List<String> allowPaths=filterPropertiess.getAllowPaths(); //获取HttpServletRequest RequestContext context=RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); //获取请求路径 String url=request.getRequestURI(); for (String allowPath : allowPaths) { if(StringUtils.contains(url, allowPath)){ //拦截 进入run() return false; } } //不拦截 return true; } @Override public Object run() throws ZuulException { //获取请求路径 RequestContext context=RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); //获取cookie中的token String token= CookieUtils.getCookieValue(request,jwtProperties.getCookieName()); try { JwtUtils.getInfoFromToken(token,jwtProperties.getPublicKey()); } catch (Exception e) { //jwt校验失败 不放行 context.setSendZuulResponse(false); context.setResponseStatusCode(HttpStatus.FORBIDDEN.value()); } return null; } }
七.链路追踪器 Zipkin
- 端口 9411
1.安装:
-
docker run -d -p 9411:9411 openzipkin/zipkin
-
访问 http://192.168.56.129:9411/
2.依赖:
注意:是给每个服务引入 不用给网关等引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
该依赖里面包含 spring-cloud-starter-sleuth、spring-cloud-sleuth-zipkin
3.配置文件:
#暴露全部监控信息
management:
endpoints:
web:
exposure
include: "*"
#zipkin所在地址
spring
zipkin
base-url: http://localhost:9411/
#zipkin采样百分比
spring
sleuth
sampler
probability:
八.配置中心
1.git服务器:
- n创建一个私有仓库
- 创建.yml文件 文件名和注册的每个服务名相同(建议所有服务的命名都带‘-’)
2.配置中心:
-
依赖:
在Spring Initlizar中选 Cloud Config-> Config Server
注意:还要引入Eureka Discovery来注册 -
配置文件(配置中心):
server: port: 9000 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ #服务的名称 spring: application: name: server-config #git配置 cloud: config: server: git: uri: (git仓库绝对路径 且去除.git后缀) username: ??? password: ??? #超时时间 timeout: 5 #分支 default-label: master
-
启动类注解:
@EnableConfigServer
-
访问方式:如http://localhost:9100/product-service.yml
/{name}-{profiles}.yml
/{label}/{name}-{profiles}.yml注意:.yml .properties .json设置一个 访问时可以互相转化
name 服务名称
profile 环境名称,开发、测试、生产
lable 仓库分支、默认master分支)
3.每个服务:
-
依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-client</artifactId> </dependency>
-
配置文件改名为:bootstrap.yml (加载顺序的问题)
-
配置文件:
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ #服务的名称 spring: application: name: product-service #指定从哪个配置中心读取 cloud: config: discovery: service-id: 配置中心名称 enabled: true profile: ? #建议用lable去区分环境,默认是lable是master分支 #label: ? (profile lable和discovery同级)
九.消息总线
- rabbitmq 15672、5672
1.安装rabbitmq:
docker run -d --name=“rabbitmq” -p 5672:5672 -p 15672:15672 rabbitmq:management
2.依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
3.配置文件(使用配置中心的都加):
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
#暴露全部的监控信息
management:
endpoints:
web:
exposure:
include: "*"
4.需要从配置文件读取信息的的类(即有@Value("${}")注解的类要加这个注解才可以读到配置):
@RefreshScope
5.发送刷新消息(post方式):
http://需要刷新的服务ip:该服务端口/actuator/bus-refresh
注意:如果有个服务有多个节点 刷新一个就可以全部刷新该服务其他节点
如果用了配置中心想要启动多个节点 通过改 idea的-Dserver.port:8888 无法再启动多节点 因为bootstarp.yml 先于idea的配置文件 所以只要改了git服务器的 再次启动 idea就可以
十.配置文件改造(使用配置中心与消息总线)
- 给服务和网关引入依赖:
<!--配置中心客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<!--config server-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
2.把服务和网关配置的所有application.yml内容放到git服务器(名称和每个服务同名 网关也是 可以给每个名字后面加上“-test“者”-dev“作为profile来区分环境)
3.给git服务器每个文件加上:
#服务的名称
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
#暴露全部的监控信息
management:
endpoints:
web:
exposure:
include: "*"
4.要用git服务器配置的服务和网关 将配置文件改名为:bootstrap.yml
5.要用git服务器配置的服务和网关 其配置文件只留下:
#指定注册中心地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
#服务的名称
spring:
application:
name: order-service
#指定从哪个配置中心读取
cloud:
config:
discovery:
service-id: 配置中心名称
enabled: true
profile: ?
6.给配置中心修改git路径
7.各个项目启动顺序
- 注册中心
- 配置中心
- 对应的服务:商品服务、订单服务。。。
- 启动网关
更多推荐
所有评论(0)