微信公众号开发是否需要建立网站,官方网站建设银行信用卡,营销型网站建设核心要素,网站如何收录文章目录 认识微服务#xff1a;SpringCloud 服务拆分及远程调用实现夸远程服务调用使用RestTemplateEureka注册中心 搭建EruekaServer注册服务服务发现 Ribbon负载均衡 修改负载均衡规则解饿加载 Nacos注册中心#xff08;nacos一部分功能#xff09; 服务注册到nacosnacos…文章目录 认识微服务SpringCloud 服务拆分及远程调用实现夸远程服务调用使用RestTemplateEureka注册中心 搭建EruekaServer注册服务服务发现 Ribbon负载均衡 修改负载均衡规则解饿加载 Nacos注册中心nacos一部分功能 服务注册到nacosnacos服务分级存储模型环境隔离 -namespace Nacos配置管理http客户端Feign 自定义Feign的配置Feign的性能优化 统一网关Gateway 网关功能搭建网关服务路由断言工厂Route Predicate Factory过滤器工厂 请求头过滤器默认过滤器自定义全局过滤器过滤器执行顺序解决跨域问题
认识微服务
单体架构将业务的所有功能集中在一个项目中开发打成一个包部署。
优点 部署简单 部署成本低 缺点 耦合度高 扩展性差
分布式架构根据业务功能对系统进行拆分每个业务模块作为独立项目开发称为一个服务。
优点 降低服务耦合度 有利于服务升级扩展 缺点 架构复杂 难度大
微服务 微服务是一种经过良好架构设计的分布式架构方案微服务架构特征
单一职责微服务拆分粒度更小每一个服务都对应唯一的业务能力能做到单一职责避免重复业务开发面向服务微服务对外暴露业务接口自治团队独立、技术独立、数据独立、部署独立隔离性强服务调用做好隔离、容错、降级、避免出现级联问题
优点 拆分粒度更小、服务更独立、耦合度更低
缺点 架构非常复杂运维、监控、部署难度提高
Dubbo、SpringCloud、SpringCloudAlibaba微服务技术对比: 企业需求 SpringCloud
SpringCloud是目前国内使用最广泛的微服务架构框架。它集成了各种微服务功能组件并基于SpringBoot实现了这些组件的自动装配。
官网地址Spring Cloud
服务拆分及远程调用
服务拆分注意事项
不同微服务不要开发相同业务微服务数据独立不要访问其他微服务的数据库微服务可以将自己的业务暴露为接口提供给其他服务调用
实现夸远程服务调用使用RestTemplate
通过Bean注解将RestTemplate对象交给spring管理在需要的地方注入RestTemplate对象
调用方法 //利用RestTemplate发送http请求//url路径String url http://localhost:8081/user/ order.getUserId();//发送http请求实现远程调用User user restTemplate.getForObject(url, User.class);Eureka注册中心
服务调用出现的问题 1.调用服务地址硬编码 2.多个服务如何选择 3.怎么知道服务提供者是否是健康状态
Eureka的作用 消费者如何向服务提供者提供具体信息的 服务启动时向eureka注册自己的信息eureka保存信息消费者根据服务名称向eureka拉取提供者信息 如果多个提供者消费者该如何选择 消费者利用负载均衡算法从服务列表中挑选一个 消费者如何感知服务器提供者的健康状态 服务提供者每隔30秒向EruekaServer发送请求报告健康状态eureka会更新服务器列表不正常得到提供者会被剔除
搭建EruekaServer
1.创建项目引入依赖
!-- eureak服务端--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-server/artifactId/dependency2.编写启动类添加EnableEurekaServer注解
3.添加application.yml文件
server:port: 10086 #服务端口
spring:application:name: eurekaserver
eureka:client:service-url: #eureka的地址信息deafultZone: http://127.0.0.1:10086/eureka启动项目后方法10086端口就可以到eureka的界面
注册服务
将服务注册到eureka的步骤
1.在服务项目中引入spring-cloud-starter-netflix-eureka-client的依赖
!-- eureka客户端依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency2.在application.yml文件编写配置
server:port: 8081
spring:datasource:url: jdbc:mysql://localhost:3306/cloud_user?useSSLfalseusername: rootpassword: ******driver-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服务发现
1.在请求路径上面把路径换成我们注册服务的名称 public Order queryOrderById(Long orderId) {// 1.查询订单Order order orderMapper.findById(orderId);//利用RestTemplate发送http请求//url路径(将路径换成需要的服务的名称)String url http://userservice/user/ order.getUserId();//发送http请求实现远程调用User user restTemplate.getForObject(url, User.class);order.setUser(user);// 4.返回return order;}2.加上RestTemplate的Bean上面加 LoadBalanced 注解
Ribbon负载均衡 ribbon的负载均衡策略 修改负载均衡规则
默认是轮询方式
1.代码方式在消费端的Application中定义一个新的IRule
Bean
public IRule randomRule(){return new RandowRule();
}2.配置文件方式配置文件只是更改一个服务的负载不是全局
userservice:ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule解饿加载
Ribbon默认是采用懒加载即第一次加载时才会去创建LoadBalanceClient请求时间会很长。而解饿加载则会在项目启动时创建降低第一次访问的耗时。
ribbon:eager-load:enabled: true #开启解饿加载clients: -userservice #指定服务名称多个服务需要在下面加 -Nacos注册中心nacos一部分功能
Nacos是阿里巴巴的产品现在是SpringCloud中的一个组件。相比Eureka功能更加丰富。
Windows启动nacos命令startup.cmd -m standalone
服务注册到nacos
1.在Cloud-demo父工程中添加Spring-cloud-alilbaba 的管理依赖 dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion2.2.5.RELEASE/versiontypepom/typescopeimport/scope/dependency2.添加nacos的客户端依赖
!-- nacos客户端依赖包--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency3.改写application.yml 文件向yml文件中加入nacos的服务地址配置 application:name: userservice #user服务名称cloud:nacos:discovery:server-addr: localhost:8848 #nacos服务地址nacos服务分级存储模型
添加服务集群属性
修改application.yml cloud:nacos:discovery:server-addr: localhost:8848 #nacos服务地址cluster-name: SH #集群名称Hz代指杭州更改服务访问规则(NacosRule负载均衡规则)
userservice:ribbon:NFLoadBalancerRuleClassName: com.alibaba.nacos.ribbon.NacosRuleNacosRule负载均衡规则 : 集群优先
环境隔离 -namespace
1.在nacos网站去创建namespace命名空间 2.配置服务所在命名空间在application.yml文件中修改 cloud:nacos:discovery:server-addr: localhost:8848cluster-name: HZnamespace: 359d6479-2271-43fa-9ca3-9cf1f1082906 #dev环境复制我们创建好的命名空间Id不同nameSpace下的服务不可见不能访问 Nacos和eureka的区别 Nacos配置管理
配置更改热更新 统一配置管理
1.引入Nacos的配置管理客户端依赖
!-- nacos的配置管理依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-config/artifactId/dependency2.在服务提供者中的resource目录中添加一个bootstrap.yml文件这个文件是引导文件优先级高于application.yml文件
spring:application:name: userservice #服务名称profiles:active: dev #环境cloud:nacos:discovery:server-addr: localhost:8848 #nacos地址config:file-extension: yaml #文件后缀名将application.yml文件中重复的配置删掉 配置自动刷新 方式一在Value注入的变量所在类上添加注解RefreshScope 方式二使用ConfigurationProperties注解 Data Component ConfigurationProperties(prefix “pattern”) public class PatternProperties { private String dateformat; }
多环境配置共享优先级
服务名-profile.yaml 服务名.yaml 本地配置
热更新的Springboot实现
1.导入jar包 dependencygroupIdcom.alibaba.boot/groupIdartifactIdnacos-config-spring-boot-starter/artifactIdversion0.2.11/version/dependency2.更改application.yaml文件
nacos:config:data-id: jc-club-oss #用于指定要获取的配置数据的ID或名称。secret-key: nacos # 用于进行访问控制的密钥用于对配置中心的访问进行认证和授权。access-key: nacos # 用于进行访问控制的密钥用于对配置中心的访问进行认证和授权。group: DEFAULT_GROUP #用于指定配置数据所属的分组这样可以更好地组织和管理配置。type: yaml #指定配置数据的类型例如 YAML、Properties 等。server-addr: http://117.72.14.166:8848/ #指定Nacos配置中心的地址包括主机名和端口。auto-refresh: true #标识是否自动刷新配置内容当配置中心的配置发生变化时客户端是否自动更新配置。remote-first: true #当配置中心不可用时是否优先使用本地缓存的配置。bootstrap:enable: true #是否启用Bootstrap配置Bootstrap配置是在Spring应用程序启动时首先加载的一组配置。3.使用NacosValue注解 NacosValue(value ${storage.service.type},autoRefreshed true)private String storageType;GetMapping(/testNacos)public String testNacos() {return storageType;}出现 failed to req API:/nacos/v1/ns/instance after all servers([localhost:8848]) tried: java.net.ConnectException: Connection refused: connect 异常
因为同时导入了Nacos的配置中心和注册中心的依赖导致
Nacos配置中心依赖 -config 注册中心 -discovery
http客户端Feign
使用之前的RestTemplate方式调用会出现一些问题
代码可读性差编程体验不统一参数复杂URL难以维护
Feign是一声明式的http客户端作用是帮助我们优雅的实现http请求的发送。
1.引入Feign依赖
!-- feign客户端依赖--
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactIdversion2.2.7.RELEASE/version
/dependency2.在启动类上添加注解开启Feign的功能
MapperScan(cn.itcast.order.mapper)
SpringBootApplication
EnableFeignClients3.编写Feign客户端
FeignClient(userservice)
public interface UserClient {GetMapping(/user/{id})User findById(PathVariable(id) Long id);
}注意若出现 Load balancer does not have available server for client: userservice 错误 需要查看服务的命名空间是否一致
微服务之间用openfeign调用要想保证微服务之间的用户上下信息一致需要添加feign的拦截器
Component
public class FeignRequestInterceptor implements RequestInterceptor {Overridepublic void apply(RequestTemplate requestTemplate) {ServletRequestAttributes requestAttributes (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request requestAttributes.getRequest();if (!ObjectUtils.isEmpty(request)) {String loginId request.getHeader(loginId);if (StringUtils.isNotBlank(loginId)){requestTemplate.header(loginId,loginId);}}}
}同时将FeignRequestInterceptor注册成Bean交给Spring管理
Configuration
public class FeignConfiguration {Beanpublic RequestInterceptor requestInterceptor(){return new FeignRequestInterceptor();}
}这样其他微服务就可以通过拦截器拿到loginId
自定义Feign的配置 配置日志级别方式一修改配置文件的方式
feign:client:config:default:# 设置日志记录级别其取值共有none、basic、headers、fullloggerLevel: FULL配置日志级别方式二声明Bean的方式
public class DefaultFeignConfiguration {Beanpublic Logger.Level logLevel(){return Logger.Level.BASIC;}
}全局有效
EnableFeignClients(defaultConfiguration DefaultFeignConfiguration.class)具体服务有效
FeignClient(value userservice,configuration DefaultFeignConfiguration.class)Feign的性能优化 使用连接池代替默认的URLConnection:
Feign添加HttpClient的支持依赖
!-- 引入HttpClient依赖--dependencygroupIdio.github.openfeign/groupIdartifactIdfeign-httpclient/artifactId/dependency配置application.yml文件
feign:httpclient:enabled: true #支持httpClient的开关max-connections: 200 #最大连接数max-connections-per-route: 50 #单个路径的最大连接数Feign的优化
日志级别尽量用basic使用HttpClient或者OkHttp代替URLConnection
Feign的最佳实践
方式二 新建module并引入feign的starter的依赖 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependency将feign的客户端和实体类抽取到新建的module中 在需要使用服务的pom文件中引入依赖 修改组件有关的import部分改成使用新建module中的包 统一网关Gateway
网关功能
身份认证和权限校验服务路由负载均衡请求限流
Springcloud 中网关的实现包括两种
gatewayzuul
搭建网关服务
1.创建一个module引入SpringCloudGateway的依赖和Nacos的服务发现依赖
!-- nacos服务发现依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency
!-- 网关gateway依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependency2.编写路由配置以及Nacos地址
server:port: 10010 #网关端口
spring:application:name: gateway #服务名称cloud:nacos:server-addr: localhost:8848gateway:routes: #网关路由配置- id: user-service #路由Id自定义只要唯一即可#uri: http://127.0.0.1:8081 #路由的目标地址http是固定地址uri: lb://userservice #路由目标地址 lb就是负载均衡后面跟服务名称predicates: #路由断言也就是判断请求是否符合路由规则的条件- Path/user/** #按照路径匹配只要以/user/开头就符合条件- id: order-serviceuri: lb://orderservicepredicates: - Path/order/** 总结
网关搭建步骤 创建项目引入nacos服务发现和gateway依赖 配置application.yml包括服务基本信息、nacos地址、路由
路由配置包括 路由id路由的唯一标示 路由目标uri路由的目标地址http代表固定地址lb代表根据服务名负载均衡 路由断言predicates判断路由的规则 路由过滤器filters对请求或响应做处理
路由断言工厂Route Predicate Factory
我们在配置文件中写的断言规则只是字符串这些字符串会被Predicate Factory读取并处理转变为路由判断的条件
例如Path/user/**是按照路径匹配这个规则是由
org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来
处理的像这样的断言工厂在SpringCloudGateway还有十几个:
名称
说明
示例
After
是某个时间点后的请求
- After2037-01-20T17:42:47.789-07:00[America/Denver]
Before
是某个时间点之前的请求
- Before2031-04-13T15:14:47.43308:00[Asia/Shanghai]
Between
是某两个时间点之前的请求
- Between2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie
请求必须包含某些cookie
- Cookiechocolate, ch.p
Header
请求必须包含某些header
- HeaderX-Request-Id, d
Host
请求必须是访问某个host域名
- Host.somehost.org,.anotherhost.org
Method
请求方式必须是指定方式
- MethodGET,POST
Path
请求路径必须符合指定规则
- Path/red/{segment},/blue/**
Query
请求参数必须包含指定参数
- Queryname, Jack或者- Queryname
RemoteAddr
请求者的ip必须是指定范围
- RemoteAddr192.168.1.1/24
Weight
权重处理
过滤器工厂
GatewayFilter是网关中提供的一种过滤器可以对进入网关的请求和微服务返回的响应做处理 名称
说明
AddRequestHeader
给当前请求添加一个请求头
RemoveRequestHeader
移除请求中的一个请求头
AddResponseHeader
给响应结果中添加一个响应头
RemoveResponseHeader
从响应结果中移除有一个响应头
RequestRateLimiter
限制请求的流量
请求头过滤器
下面我们以AddRequestHeader 为例来讲解。 需求给所有进入userservice的请求添加一个请求头Truthitcast is freaking awesome! 只需要修改gateway服务的application.yml文件添加路由过滤即可
spring:cloud:gateway:routes:- id: user-service uri: lb://userservice predicates: - Path/user/** filters: # 过滤器- AddRequestHeaderTruth, Itcast is freaking awesome! # 添加请求头当前过滤器写在userservice路由下因此仅仅对访问userservice的请求有效。
默认过滤器
如果要对所有的路由都生效则可以将过滤器工厂写到default下。格式如下
spring:cloud:gateway:routes:- id: user-service uri: lb://userservice predicates: - Path/user/**default-filters: # 默认过滤项- AddRequestHeaderTruth, Itcast is freaking awesome! 自定义全局过滤器
需求定义全局过滤器拦截请求判断请求的参数是否满足下面条件 参数中是否有authorization authorization参数值是否为admin
如果同时满足则放行否则拦截
实现
在gateway中定义一个过滤器
package cn.itcast.gateway.filters;import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;Order(-1)
Component
public class AuthorizeFilter implements GlobalFilter {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1.获取请求参数MultiValueMapString, String params exchange.getRequest().getQueryParams();// 2.获取authorization参数String auth params.getFirst(authorization);// 3.校验if (admin.equals(auth)) {// 放行return chain.filter(exchange);}// 4.拦截// 4.1.禁止访问设置状态码exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);// 4.2.结束处理return exchange.getResponse().setComplete();}
}过滤器执行顺序
请求进入网关会碰到三类过滤器当前路由的过滤器、DefaultFilter、GlobalFilter
请求路由后会将当前路由过滤器和DefaultFilter、GlobalFilter合并到一个过滤器链集合中排序后依次执行每个过滤器 排序的规则
每一个过滤器都必须指定一个int类型的order值order值越小优先级越高执行顺序越靠前。GlobalFilter通过实现Ordered接口或者添加Order注解来指定order值由我们自己指定路由过滤器和defaultFilter的order由Spring指定默认是按照声明顺序从1递增。当过滤器的order值一样时会按照 defaultFilter 路由过滤器 GlobalFilter的顺序执行。
详细内容可以查看源码
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()方法是先加载defaultFilters然后再加载某个route的filters然后合并。
org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()方法会加载全局过滤器与前面的过滤器合并后根据order排序组织过滤器链
解决跨域问题
在gateway服务的application.yml文件中添加下面的配置
spring:cloud:gateway:# 。。。globalcors: # 全局的跨域处理add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题corsConfigurations:[/**]:allowedOrigins: # 允许哪些网站的跨域请求 - http://localhost:8090allowedMethods: # 允许的跨域ajax的请求方式- GET- POST- DELETE- PUT- OPTIONSallowedHeaders: * # 允许在请求中携带的头信息allowCredentials: true # 是否允许携带cookiemaxAge: 360000 # 这次跨域检测的有效期网关提示503错误并且配置的地址信息都符合 查看是否配置的负载均衡的依赖 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-loadbalancer/artifactId/dependency