当前位置: 首页 > news >正文

为什么要建设o2o网站进出口网站贸易平台有哪些

为什么要建设o2o网站,进出口网站贸易平台有哪些,中国行业研究报告网,网站后台示演目录 前言初识微服务单体架构分布式架构微服务架构初见SpringCloud微服务治理分布式服务架构案例 微服务组件及使用Eureka注册中心提供者和消费者Eureka的结构和作用搭建Eureka服务注册服务服务发现Eureka注册服务总结 Ribbon负载均衡原理负载均衡原理负载均衡策略懒加载 Nacos… 目录 前言初识微服务单体架构分布式架构微服务架构初见SpringCloud微服务治理分布式服务架构案例 微服务组件及使用Eureka注册中心提供者和消费者Eureka的结构和作用搭建Eureka服务注册服务服务发现Eureka注册服务总结 Ribbon负载均衡原理负载均衡原理负载均衡策略懒加载 Nacos注册中心认识安装nacosNacos快速入门Nacos服务分级存储模型Nacos环境隔离Nacos和Eureka的区别 Nacos管理配置统一配置管理配置热更新配置共享搭建Nacos集群 Feign远程调用Feign替代RestTemplate自定义配置Feign的性能优化Feign的最佳实践 Gateway服务网关初识Gateway网关Gateway快速入门断言工厂过滤器工厂全局过滤器跨域问题 未完待续 前言 本篇是记录黑马的SpringCloud学习过程中的笔记该篇为实用篇的上篇详尽记录了微服务架构Eurake注册中心Nacos注册及配置管理中心RibbonFeign和Gateway网关而DockerMQES等服务组件在实用篇下篇继续记录最后感谢您的阅览愿您终有所获 初识微服务 单体项目随身业务的增加不可避免的就是项目越来越庞大很不利于后期项目的维护导致项目结构变的很臃肿耦合度高所以现在的服务架构也从单体项目演变为分布式和微服务架构 单体架构 单体架构将业务的所有功能集中在一个项目中开发打成一个包部署到服务器上 优点是 简单便捷易上手操作难度低 缺点是 随着业务的增加结构逐渐臃肿耦合度较高不易于维护 分布式架构 分布式架构根据业务功能对系统做拆分每个业务功能模块作为独立项目开发称为一个服务。 这里引用颜老师的一句话 分布式的核心就一个字拆。只要是将一个项目拆分成了多个模块并将这些模块分开部署那就算是分布式。 分布式的拆分可以分为水平拆分和垂直拆分 水平拆分 字面上理解水平拆分就是按照三层模型来拆“三层架构”拆分成 表示层jspservlet、业务逻辑层service和数据访问层dao然后再分开部署各个服务器上之间通过dubbo或RPC进行进行整合 垂直拆分 根据业务进行拆分。例如可以根据业务逻辑比如常见的电商系统可以把用户模块当作一个独立的项目同理订单聊天也是可以拆分为一个独立项目的。显然这三个拆分后的项目仍然可以作为独立的项目使用。像这种拆分的方法就成为垂直拆分。 分布式架构的优缺点 优点 降低服务耦合有利于服务升级和拓展 缺点 服务调用关系错综复杂 微服务架构 微服务可以理解为一种非常细粒度的垂直拆分。例如以上“订单项目”本来就是垂直拆分后的子项目但实际上“订单项目”还能进一步拆分为“购物项目”、“结算项目”和“售后项目”。 微服务是不能再拆的“微小”服务类似于“原子性” 微服务的架构四大特征 单一职责微服务拆分粒度更小每一个服务都对应唯一的业务能力做到单一职责自治团队独立、技术独立、数据独立独立部署和交付面向服务服务提供统一标准的接口与语言和技术无关隔离性强服务调用做好隔离、容错、降级避免出现级联问题 微服务的上述特性其实是在给分布式架构制定一个标准进一步降低服务之间的耦合度提供服务的独立性和灵活性。做到高内聚低耦合。 因此可以认为微服务是一种经过良好架构设计的分布式架构方案 ①优点拆分粒度更小、服务更独立、耦合度更低 ②缺点架构非常复杂运维、监控、部署难度提高 下图就是标准的微服务架构的图解 每个模块的作用与组合结构如下图关系所示 注意微服务不仅仅是SpringCloud 初见SpringCloud SpringCloud作为Spring大家族之一也是目前国内使用最广泛的微服务框架SpringCloud集成了各种微服务功能组件并基于SpringBoot实现了这些组件的自动装配从而提供了良好的开箱即用体验。 下面是一些常见的组件 SpringCloud底层是依赖于SpringBoot的并且有版本的兼容关系 微服务治理 在国内最知名的就是SpringCloud和阿里巴巴的Dubbo。后来阿里出的最火热的SpringCloudAlibaba框架兼容了前两种服务协议DubboFeign 微服务架构落地的四种方案 分布式服务架构案例 现在来演示一个小小的服务拆分的demo示例 例如现在我们把user模块给拆分出来把order模块给拆分出来步骤如下 ①首先为两个项目建立各自的数据库导入对应的数据sql文件创建表 ②先创建boot主项目如果是b站黑马过来的直接导入资料文件夹下的demo项目然后创建其他模块的项目 注意一点cloud底层是依赖boot的所以cloud和boot版本需要一一对应这重要具体对应关系如下表 例如下面是主项目工程的pom文件 主项目工程中的依赖 dependencyManagementdependencies!-- springCloud --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversion${spring-cloud.version}/versiontypepom/typescopeimport/scope/dependency!-- mysql驱动 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion${mysql.version}/version/dependency!--mybatis--dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion${mybatis.version}/version/dependency/dependencies/dependencyManagementdependenciesdependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependency/dependencies然后创建子模块项目boot版本高了创建好后手动降低版本就是在parent那块把version手动调整刷新就好了 具体项目结构如下图 然后完善子模块先写一个基本查询业务mapper层service层controller层没什么好说的如果用上mp的api甚至可以更快。 接下来把user-service 和 cloud-service项目都启动起来然后浏览器访问http://localhost:8080/order/101可以看到订单信息的数据已经查询出来了 ③实现远程调用 但是如上图其中的user属性是null这是因为order表中没有user字段如果是以前的单体项目就是直接来个两表联查但是对于微服务项目每个模块负责各自的业务不允许业务重复这是就需要远程调用出手了 我们需要在order-service中 向user-service发起一个http的请求调用http://localhost:8081/user/{userId}这个接口。 大概的步骤是这样的 注册一个RestTemplate的实例到Spring容器修改order-service服务中的OrderService类中的queryOrderById方法根据Order对象中的userId查询User将查询的User填充到Order对象一起返回 实现如下 在order-service项目中的启动类里注册RestTemplate实例 MapperScan(cn.order.mapper) SpringBootApplication public class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}Beanpublic RestTemplate restTemplate(){return new RestTemplate();} }修改order-service服务中的service层下的OrderService类中的queryOrderById方法 Service public class OrderService {Resourceprivate OrderMapper orderMapper;Resourceprivate RestTemplate restTemplate;public Order queryOrderById(Long orderId) {// 1.查询订单Order order orderMapper.findById(orderId);// 2.远程查询user// 2.1 url地址String url http://localhost:8081/user order.getUserId();// 2.2 发起调用User user restTemplate.getForObject(url, User.class);// 3. 存入orderorder.setUser(user);// 4.返回return order;} }然后再次重启两个服务再去浏览器访问order服务会发现user也查询出来了 微服务组件及使用 Eureka注册中心 提供者和消费者 如上面的分布式案例在需要其他模块数据信息时是用远程调用对应的模块服务其中在服务调用关系中会有两个不同的角色 服务提供者一次业务中被其它微服务调用的服务。提供接口给其它微服务 服务消费者一次业务中调用其它微服务的服务。调用其它微服务提供的接口 服务提供者与服务消费者的角色并不是绝对的而是相对于业务而言。 下面一个例子便于理解 如果服务A调用了服务B而服务B又调用了服务C服务B的角色是什么 对于A调用B的业务而言A是服务消费者B是服务提供者对于B调用C的业务而言B是服务消费者C是服务提供者 因此服务B既可以是服务提供者也可以是服务消费者。 Eureka的结构和作用 如果服务的提供者部署了多个实例在进行服务的远程调用时会发生以下问题 order-service在发起远程调用的时候该如何得知user-service实例的ip地址和端口有多个user-service实例地址order-service调用时该如何选择order-service如何得知某个user-service实例是否依然健康是不是已经宕机 而在这种集群项目结构下Eureka义不容辞的来了 Eureka是SpringCloud中的注册中心也是最广为人知的注册中心 结构如下 回答之前的各个问题。 问题1order-service如何得知user-service实例地址 获取地址信息的流程如下 user-service服务实例启动后将自己的信息注册到eureka-serverEureka服务端。这个叫服务注册eureka-server保存服务名称到服务实例地址列表的映射关系order-service根据服务名称拉取实例地址列表。这个叫服务发现或服务拉取 问题2order-service如何从多个user-service实例中选择具体的实例 order-service从实例列表中利用负载均衡算法例如轮询随机权重选中一个实例地址向该实例地址发起远程调用 问题3order-service如何得知某个user-service实例是否依然健康是不是已经宕机 user-service会每隔一段时间默认30秒向eureka-server发起请求报告自己状态称为心跳当超过一定时间没有发送心跳时eureka-server会认为微服务实例故障将该实例从服务列表中剔除order-service拉取服务时就能将故障实例排除了 注意一个微服务既可以是服务提供者又可以是服务消费者因此eureka将服务注册、服务发现等功能统一封装到了eureka-client端 搭建Eureka服务 1.引入eureka依赖 注册中心服务端eureka-server这必须是一个独立的微服务独立的子项目建议创建maven项目如果你想用boot我也没意见只需要在它的pom文件中加入eureka的依赖即可其他的例如版本信息和其他依赖都在父工程中加了它是继承了父工程的依赖 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-server/artifactId /dependency2.编写启动类 给eureka-server服务编写一个启动类一定要添加一个EnableEurekaServer注解开启eureka的注册中心功能 SpringBootApplication EnableEurekaServer public class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class, args);} }3.编写配置文件 resource文件夹下编写一个application.yml文件 server:port: 10086 spring:application:name: eureka-server eureka:client:service-url: defaultZone: http://127.0.0.1:10086/eureka4.启动服务 配置完毕后可以启动服务看看是否搭建成功访问http://localhost:10086/ 注册服务 1.引入依赖 不同于上面搭建eureka服务的依赖了这回注入的是client dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId /dependency注在服务提供者的pom文件中引入该依赖 2.配置文件 在服务提供者user-service中修改application.yml文件添加服务名称、eureka服务地址 spring:application:name: userservice eureka:client:service-url:defaultZone: http://localhost:10086/eureka启动多个user-service实例可选 这里是为了演示一个服务有多个实例的场景时轮询策略远程调用我们添加一个SpringBoot的启动配置再启动一个user-service。 首先复制原来的user-service启动配置 然后在弹出的窗口中作一下配置 现在SpringBoot窗口会出现两个user-service启动配置第一个是8081端口第二个是8082端口。 启动新添的user-server实例 现在再访问http://localhost:10086 看看服务是否已经注册成功 服务发现 将order-service的逻辑修改向eureka-server拉取user-service的信息实现服务发现。 1.引入依赖 服务发现、服务注册统一都封装在eureka-client依赖因此这一步与服务注册时一致。 在order-service的pom文件中引入下面的eureka-client依赖 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId /dependency2.配置文件 服务发现也需要知道eureka地址因此第二步与服务注册一致都是配置eureka信息 在order-service中修改application.yml文件添加服务名称、eureka地址 spring:application:name: orderservice eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka3.服务拉取和负载均衡 最后我们要去eureka-server中拉取user-service服务的实例列表并且实现负载均衡。 在服务消费者order-service的OrderApplication中给RestTemplate这个Bean添加一个LoadBalanced注解轮询策略 修改order-service服务中的OrderService类中的queryOrderById方法。修改访问的url路径用服务名代替ip、端口 spring会自动帮助我们从eureka-server端根据userservice这个服务名称获取实例列表而后完成负载均衡。 4.最后测试结果 成功远程调用了user-service服务查询道理user信息 Eureka注册服务总结 1搭建EurekaServer 引入eureka-server依赖添加EnableEurekaServer注解·在application.yml中配置eureka地址 2服务注册 引入eureka-client依赖在application.yml中配置eureka地址 3服务发现 引入eureka-client依赖在application.yml中配置eureka地址给RestTemplate添加LoadBalanced注解·用服务提供者的服务名称远程调用 Ribbon负载均衡原理 Ribbon谐音瑞本我怕自己读不标准记一下 上面做了Eureka服务注册后就自动拉取服务并完成了负载均衡。那什么时候自动拉取什么时候做的负载均衡呢下面就来探究负载均衡原理 负载均衡原理 1.当服务消费者发起远程调用服务请求 2.其中的LoadBalancerIntercepor会对请求进行拦截 然后做了几件事 request.getURI()获取请求uri本例中就是 http://user-service/user/8originalUri.getHost()获取uri路径的主机名其实就是服务id也就是user-servicethis.loadBalancer.execute()处理服务id和用户请求。 3.断点下一步继续跟进上面的execute方法这一步完成了获取eureka中注册的对应的服务并获取了指定的负载均衡策略 getLoadBalancer(serviceId)根据服务id获取ILoadBalancer而LoadBalancer会拿着服务id去eureka中获取服务列表并保存起来。getServer(loadBalancer)利用内置的负载均衡算法从服务列表中选择一个。本例中可以看到获取了8082端口的服务 4.负载均衡策略IRule 在上面的代码中可以看到获取服务使通过一个getServer方法来做负载均衡: 下面就是源码跟进不断跟到底看看到底是谁在帮我们做负载均衡 最后下面是一个负载均衡流程图这个图会更容易理解从请求远程服务调用负载均衡的流程 基本流程如下 拦截我们的RestTemplate请求http://userservice/user/1RibbonLoadBalancerClient会从请求url中获取服务名称也就是user-serviceDynamicServerListLoadBalancer根据user-service到eureka拉取服务列表eureka返回列表localhost:8081、localhost:8082IRule利用内置负载均衡规则从列表中选择一个例如localhost:8081RibbonLoadBalancerClient修改请求地址用localhost:8081替代userservice得到http://localhost:8081/user/1发起真实请求 负载均衡策略 Ribbon的负载均衡规则是一个叫做IRule的接口来定义的每一个子接口都是一种规则 不同规则的含义如下 内置负载均衡规则类规则描述RoundRobinRule简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。AvailabilityFilteringRule对以下两种服务器进行忽略 1在默认情况下这台服务器如果3次连接失败这台服务器就会被设置为“短路”状态。短路状态将持续30秒如果再次连接失败短路的持续时间就会几何级地增加。 2并发数过高的服务器。如果一个服务器的并发连接数过高配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限可以由客户端的..ActiveConnectionsLimit属性进行配置。WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长这个服务器的权重就越小。这个规则会随机选择服务器这个权重值会影响服务器的选择。ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。BestAvailableRule忽略那些短路的服务器并选择并发数较低的服务器。RandomRule随机选择一个可用的服务器。RetryRule重试机制的选择逻辑 默认的实现就是ZoneAvoidanceRule是一种轮询方案 自定义负载均衡策略 通过定义IRule实现可以修改负载均衡规则有两种方式 代码方式在order-service中的OrderApplication类启动类中定义一个新的IRule Bean public IRule randomRule(){return new RandomRule(); }这个是全局配置order-service这个服务在调用其他微服务也都是会遵循这个配置的策略 2.配置文件方式在order-service的application.yml文件中添加新的配置也可以修改规则 userservice: # 给某个微服务配置负载均衡规则这里是userservice服务ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 这个在yml文件中添加的配置只在当前微服务有效是局部配置 注意一般用默认的负载均衡规则不做修改。 懒加载 Ribbon默认是采用懒加载即第一次访问时才会去创建LoadBalanceClient请求时间会很长。 而饥饿加载则会在项目启动时创建降低第一次访问的耗时通过下面配置开启饥饿加载 ribbon:eager-load:enabled: trueclients: userserviceNacos注册中心 由于国内公司一般都推崇阿里巴巴的技术比如注册中心SpringCloudAlibaba也推出了一个名为Nacos的注册中心相比Eureka功能更加丰富使用更广泛 认识安装nacos nacos1.4.1下载nacos下载 提取码olww 下载完毕后在bin目录下键入cmd启动 输入以下命令因为它默认是集群启动 这里设置为单体启动 startup.cmd -m standalone浏览器跟上这个地址 http://localhost:8848/nacos/index.html 用户名密码都是nacos登录进去 Nacos快速入门 1.父工程导入SpringCloudAlibaba的依赖 dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion2.2.6.RELEASE/versiontypepom/typescopeimport/scope /dependency2.在user-service和order-service中的pom文件中引入nacos-discovery依赖 dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency记得注释掉原来的eureka依赖 3.配置nacos地址 在导入nacos依赖的项目的yml文件中加上nacos配置 spring:cloud:nacos:server-addr: localhost:88484.启动服务然后再前面打开的nacos网页中查看 Nacos服务分级存储模型 一般大厂都会做集群来容灾保证当本地服务宕机后仍然能够正常运转访问别处的服务 比如当它的杭州服务器发生故障导致宕机那么它就会访问上海的服务来保证功能的正常运转 有点互为备胎的意思 Nacos就将同一机房内的实例 划分为一个集群。 user-service是服务一个服务可以包含多个集群如杭州、上海每个集群下可以有多个实例形成分级模型——其实就是分为服务——集群——实例这三层 微服务互相访问时应该尽可能访问同集群实例因为本地访问速度更快。当本集群内不可用时才访问其它集群 给服务配置集群 yml配置文件中加上 名称随意 NacosRule负载均衡策略 userservice:ribbon:NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 ①优先选择同集群服务实例列表 ②本地集群找不到提供者才去其它集群寻找并且会报警告 ③确定了可用实例列表后再采用随机负载均衡挑选实例 权重负载均衡 实际部署中会出现这样的场景 服务器设备性能有差异部分实例所在机器性能较好另一些较差我们希望性能好的机器承担更多的用户请求。 但默认情况下NacosRule是同集群内随机挑选不会考虑机器的性能问题。 但我们需要考虑到能者多劳所以权重配置就来了根据不同的权重设置可以控制访问的频率权重越大访问频率越高 当权重为0时就不会通过该服务器进行访问了 以前一个服务要版本更新升级就需要服务重启但是不可能光天化日之下升级导致用户都访问失败往往是在夜深人静时偷偷升级。不是很方便。 而权重策略的作用之一就是项目更新升级时把对应的服务器权重调低放入少量用户测试看看刚上线功能是否通过做到平滑升级。 举个例子某种游戏有时候会发出公告不停服更新就是这么来的 实例的权重控制 ①Nacos控制台可以设置实例的权重值 ②0~1之间同集群内的多个实例权重越高被访问的频率越高 ③权重设置为0则完全不会被访问 Nacos环境隔离 默认情况下所有service、data、group都在同一个namespace名为public Nacos提供了namespace来实现环境隔离功能。 nacos中可以有多个namespacenamespace下可以有group、service等不同namespace之间相互隔离例如不同namespace的服务互相不可见 具体操作如下 Nacos环境隔离 namespace用来做环境隔离每个namespace都有唯一id不同namespace下的服务不可见 Nacos和Eureka的区别 Nacos谐音哪克四Eureka谐音衣锐咔我自己英语读的不标准记录一下免得下回和别人聊天只会读拼写。搞得别人一脸懵圈说你和我说的是同一个技术吗 回归正题 Nacos是主动把注册服务列表推送给服务消费者如果有服务挂掉了就立马推送新的服务列表 Eureka是定时从注册中心拉去服务列表所以它的服务列表更新效率稍逊于Nacos Nacos的服务实例分为两种类型 临时实例如果实例宕机超过一定时间不主动发送心跳信息会从服务列表剔除默认的类型。 非临时实例nacos会主动询问实例的心跳信息如果实例宕机也不会从服务列表剔除也可以叫永久实例。 在配置中设置实例类型 最后总结 Nacos与eureka的共同点 都支持服务注册和服务拉取都支持服务提供者心跳方式做健康检测 Nacos与Eureka的区别 Nacos支持服务端主动检测提供者状态临时实例采用心跳模式非临时实例采用主动检测模式临时实例心跳不正常会被剔除非临时实例则不会被剔除Nacos支持服务列表变更的消息推送模式服务列表更新更及时Nacos集群默认采用AP方式当集群中存在非临时实例时采用CP模式Eureka采用AP方式 Nacos管理配置 统一配置管理 使用场景 当一个集群中微服务过多成千上百个时需要更改其中一个微服务的配置信息那么其他远程调用该服务的成千上百个服务都需要重启这在生产环境中几乎是不可能的 所以我们需要一种统一配置管理方案可以集中管理所有实例的配置 Nacos一方面可以将配置集中管理另一方可以在配置变更时及时通知微服务实现配置的热更新 添加配置信息 注意项目的核心配置需要热更新的配置才有放到nacos管理的必要。基本不会变更的一些配置还是保存在微服务本地比较好。 从微服务中拉去服务 微服务要拉取nacos中管理的配置并且与本地的application.yml配置合并才能完成项目启动。 而nacos的地址等配置信息在applicationyml中但如果尚未读取application.yml又如何得知nacos地址 因此spring引入了一种新的配置文件bootstrap.yaml文件会在application.yml之前被读取 1.导入Nacos配置管理依赖 !--nacos配置管理依赖-- dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-config/artifactId /dependency2.添加bootstrap.yaml 然后在resource文件夹下中添加一个bootstrap.yaml文件 spring:application:name: userservice # 服务名称profiles:active: dev #开发环境这里是dev cloud:nacos:server-addr: localhost:8848 # Nacos地址config:file-extension: yaml # 文件后缀名这里会根据spring.cloud.nacos.server-addr获取nacos地址再根据nameactiveextension来读取对应配置 3.添加nacos配置并读取 在user-service中的UserController中添加业务逻辑读取在Nacos中添加的pattern.dateformat配置 按照我们规定的格式完成日期格式化并返回 表示成功拉去到了Nacos中的配置信息了 配置热更新 Nacos中的配置文件变更后微服务无需重启就可以感知就是直接刷新网页就会更新配置。可以通过下面两种配置方式实现: 方式一 在Value注入的变量所在类上添加注解RefreshScope 方式二 使用ConfigurationProperties注解代替Value注解。 在user-service服务中添加一个类读取patterrn.dateformat属性 Component Data ConfigurationProperties(prefix pattern) public class PatternProperties {private String dateformat; }在UserController中使用这个类代替Value 配置共享 有一些属性在开发测试等多个环境值都是一样的为避免修改该配置的值要取一个一个的修改就引用了配置共享方法把相同的配置放在共享配置中就像类中的public static修饰的变量一样 微服务启动时会去nacos读取多个配置文件例如 [spring.application.name]-[spring.profiles.active].yaml例如userservice-dev.yaml [spring.application.name].yaml例如userservice.yaml 而[spring.application.name].yaml不包含环境因此可以被多个环境共享。 配置优先级 远程专属配置 远端共享配置 本地配置 搭建Nacos集群 学习阶段没有那么多机子只能搞搞简略版把服务都配在本地一台上 前提搭建mysql集群初始化数据库表条件有限也可以只用一台mysql数据库 ①把nacos压缩包解压缩 ②进入nacos的conf目录修改配置文件cluster.conf.example重命名为cluster.conf ③然后添加内容因为只是把三台配在本地没有三台服务器所以都是本地ip端口选没使用的就行 127.0.0.1:8845 127.0.0.1.8846 127.0.0.1.8847④修改application.properties文件添加数据库配置 ⑤将nacos文件夹复制三份然后分别修改三个文件夹中的application.properties nacos1: server.port8845nacos2: server.port8846nacos3: server.port8847⑥然后分别启动三个nacos节点、 就是bin目录下的startup.cmd因为它默认就是集群启动的双击即可 ⑦使用nginx进行反向代理 修改conf/nginx.conf文件配置如下 直接复制进去就行了 upstream nacos-cluster {server 127.0.0.1:8845;server 127.0.0.1:8846;server 127.0.0.1:8847; }server {listen 80;server_name localhost;location /nacos {proxy_pass http://nacos-cluster;} }⑧代码中application.yml文件配置如下 spring:cloud:nacos:server-addr: localhost:80 # Nacos地址这时候在nacos中创建新的配置会存到数据库里面去完成持久化了 优化 实际部署时需要给做反向代理的nginx服务器设置一个域名这样后续如果有服务器迁移nacos的客户端也无需更改配置. Nacos的各个节点应该部署到多个不同服务器做好容灾和隔离 Feign远程调用 前面都是完成了服务注册,配置中心nacos相关但是服务拉取的部分是用的RestTemplate 以前利用RestTemplate发起远程调用的代码 存在下面的问题 •代码可读性差编程体验不统一 •参数复杂URL难以维护 Feign是一个声明式的http客户端其作用就是帮助我们优雅的实现http请求的发送解决上面提到的问题。 Feign替代RestTemplate ①引入Feign依赖 pom文件中引入feign的依赖 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId /dependency②添加注解 在启动类上添加注解开启Feign的功能 ③编写Feign的客户端 下面是以以前demo的order-service为例 FeignClient(userservice) public interface UserClient {GetMapping(/user/{id})User findById(PathVariable(id) Long id); }这个客户端主要是基于SpringMVC的注解来声明远程调用的信息比如 服务名称userservice请求方式GET请求路径/user/{id}请求参数Long id返回值类型User 这样Feign就可以帮助我们发送http请求无需自己使用RestTemplate来发送了。 ④在业务方法中替换以前的RestTemplate 就不会像以前那样在业务代码中添加url可读性很低代码也不简洁 最后可以看到最后也完成了远程调用而且代码更加简洁同时多试几次会发现feign不仅实现了服务拉取而且实现了负载均衡 ⑤总结 使用Feign的步骤 ① 引入依赖 ② 添加EnableFeignClients注解 ③ 编写FeignClient接口 ④ 使用FeignClient中定义的方法代替RestTemplate 自定义配置 Feign可以支持很多的自定义配置如下表所示 类型作用说明feign.Logger.Level修改日志级别包含四种不同的级别NONE、BASIC、HEADERS、FULLfeign.codec.Decoder响应结果的解析器http远程调用的结果做解析例如解析json字符串为java对象feign.codec.Encoder请求参数编码将请求参数编码便于通过http请求发送feign. Contract支持的注解格式默认是SpringMVC的注解feign. Retryer失败重试机制请求失败的重试机制默认是没有不过会使用Ribbon的重试 一般情况下默认值就能满足我们使用如果要自定义时只需要创建自定义的Bean覆盖默认Bean即可。 配置文件方式 基于配置文件修改feign的日志级别可以针对单个服务 feign: client:config: userservice: # 针对某个微服务的配置loggerLevel: FULL # 日志级别 也可以针对所有服务 feign: client:config: default: # 这里用default就是全局配置如果是写服务名称则是针对某个微服务的配置loggerLevel: FULL # 日志级别 Java代码方式 也可以基于Java代码来修改日志级别先声明一个类然后声明一个Logger.Level的对象 public class DefaultFeignConfiguration {Beanpublic Logger.Level feignLogLevel(){return Logger.Level.BASIC; // 日志级别为BASIC} }如果要全局生效将其放到启动类的EnableFeignClients这个注解中 EnableFeignClients(defaultConfiguration DefaultFeignConfiguration .class) 如果是局部生效则把它放到对应的FeignClient这个注解中 FeignClient(value userservice, configuration DefaultFeignConfiguration .class) 而日志的级别分为四种 NONE不记录任何日志信息这是默认值。BASIC仅记录请求的方法URL以及响应状态码和执行时间HEADERS在BASIC的基础上额外记录了请求和响应的头信息FULL记录所有请求和响应的明细包括头信息、请求体、元数据。 调试错误时可以用FULL但是平常时候一般还是用NONE 和 BASIC Feign的性能优化 Feign底层发起http请求依赖于其它的框架。其底层客户端实现包括 •URLConnection默认实现不支持连接池所以性能不是很好因为连接池可以减少连接的创建和销毁的连接损耗因为每次连接都需要三次握手和四次挥手 •Apache HttpClient 支持连接池 •OKHttp支持连接池 因此提高Feign的性能主要手段就是使用连接池代替默认的URLConnection。 这里用Apache的HttpClient来演示。 ①引入依赖 !--httpClient的依赖 -- dependencygroupIdio.github.openfeign/groupIdartifactIdfeign-httpclient/artifactId /dependency②配置文件中做相应的配置 feign:client:config:default: # default全局的配置loggerLevel: BASIC # 日志级别BASIC就是基本的请求和响应信息httpclient:enabled: true # 开启feign对HttpClient的支持max-connections: 200 # 最大的连接数max-connections-per-route: 50 # 每个路径的最大连接数总结Feign的优化 1.日志级别尽量用basic 2.使用HttpClient或OKHttp代替URLConnection ① 引入feign-httpClient依赖 ② 配置文件开启httpClient功能设置连接池参数 Feign的最佳实践 最佳实践就是前辈们不断踩坑后总结的经验也是Feign最好的一种使用方式 feign客户端 UserController 观察可以发现Feign的客户端与服务提供者的controller代码非常相似为了简化这种重复的代码编写下面有两种实现方式 继承方式 一样的代码可以通过继承来共享 1定义一个API接口利用定义方法并基于SpringMVC注解做声明。 2Feign客户端和Controller都集成改接口 优点 简单容易实现了代码共享 缺点 服务提供方、服务消费方紧耦合 参数列表中的注解映射并不会继承因此Controller中必须再次声明方法、参数列表、注解 抽取方式 将Feign的Client抽取为独立模块并且把接口有关的POJO、默认的Feign配置都放到这个模块中提供给所有消费者使用。 例如将UserClient、User、Feign的默认配置都抽取到一个feign-api包中所有微服务引用该依赖包即可直接使用。 缺点一些服务不需要的依赖也被统一引入了 总结 Feign的最佳实践: ①让controller和FeignClient继承同一接口 ②将FeignClient、POJO、Feign的默认配置都定义到一个项目中供所有消费者使用 代码实现 下面是对第二种方式——抽取的实现 第一步创建feign模块做统一api并把前面demo中order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中 第二步在feign-api中然后引入feign的starter依赖 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId /dependency第三步可以把前面order-service中的实体类和feign的Client都删掉了在其pom文件中导入刚编写的eign-api模块 修改order-service中的所有与上述三个组件有关的导包部分改成导入feign-api中的包 第四步注入到Spring容器中 当定义的FeignClient不在SpringBootApplication的扫描包范围时这些FeignClient无法使用。有两种方式解决 方式一指定FeignClient所在包 EnableFeignClients(basePackages cn.itcast.feign.clients)方式二指定FeignClient字节码 EnableFeignClients(clients {UserClient.class})一般推荐用第二种精准打击 Gateway服务网关 初识Gateway网关 Gateway网关是我们服务的门卫是所有微服务的统一入口。 网关的三个核心的功能如下 ①权限控制网关作为微服务入口需要校验用户是是否有请求资格如果没有则进行拦截。 ②路由和负载均衡一切请求都必须先经过gateway但网关不处理业务而是根据某种规则把请求转发到某个微服务这个过程叫做路由。当然路由的目标服务有多个时还需要做负载均衡。 ③限流当请求流量过高时在网关中按照下流的微服务能够接受的速度来放行请求避免服务压力过大。 在SpringCloud中网关的实现包括两种 gatewayzuul Zuul是基于Servlet的实现属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux属于响应式编程的实现具备更好的性能。 Gateway快速入门 要实现网关的基本路由功能基本步骤如下 创建SpringBoot工程gateway引入网关依赖编写启动类编写基础配置和路由规则启动网关服务进行测试 代码实现 1.创建一个gateway模块作为服务引入gateway和nacos服务发现依赖 建议创建maven工程boot工程的话要改版本 !--网关-- dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId /dependency !--nacos服务发现依赖-- dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency2.在gateway模块中编写启动类 SpringBootApplication public class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);} }3.配置yml文件给其添加对应配置信息 server:port: 10010 # 网关端口 spring:application:name: gateway # 服务名称cloud:nacos:server-addr: localhost:8848 # nacos地址gateway:routes: # 网关路由配置- id: user-service # 路由id自定义只要唯一即可# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址uri: lb://userservice # 路由的目标地址 lb就是负载均衡后面跟服务名称predicates: # 路由断言也就是判断请求是否符合路由规则的条件- Path/user/** # 这个是按照路径匹配只要以/user/开头就符合要求将符合Path 规则的一切请求都代理到 uri参数指定的地址。 我们将 /user/**开头的请求代理到lb://userservicelb是负载均衡根据服务名拉取服务列表实现负载均衡。 4.启动网关服务访问网关服务端口测试结果如下图可以通过网关然后访问到服务 报错503 新版本的nacos一定要加上 spring-cloud-starter-loadbalancer 依赖用于替换ribbon 网关路由的流程图 最后总结流程步骤 网关搭建步骤 创建项目引入nacos服务发现和gateway依赖 创建GatewayApplication启动类 配置application.yml包括服务基本信息、nacos地址、路由 路由配置包括 路由id路由的唯一标示一般为服务名但要求不重复 路由目标uri路由的目标地址http代表固定地址lb代表根据服务名负载均衡 路由断言predicates判断路由的规则 路由过滤器filters对请求或响应做处理 断言工厂 我们在配置文件中写的断言规则只是字符串这些字符串会被Predicate Factory读取并处理转变为路由判断的条件 例如Path/user/**是按照路径匹配 断言(assertion)是一种在程序中的一阶逻辑(如一个结果为真或假的逻辑判断式)目的为了表示与验证软件开发者预期的结果——当程序执行到断言的位置时对应的断言应该为真。若断言不为真时程序会中止执行并给出错误信息。 大白话就是判断返回值是true或者false 断言工厂在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.pHeader请求必须包含某些header- HeaderX-Request-Id, \dHost请求必须是访问某个host域名- Host.somehost.org,.anotherhost.orgMethod请求方式必须是指定方式- MethodGET,POSTPath请求路径必须符合指定规则- Path/red/{segment},/blue/**Query请求参数必须包含指定参数- Queryname, Jack或者- QuerynameRemoteAddr请求者的ip必须是指定范围- RemoteAddr192.168.1.1/24Weight权重处理 不需要记随用随查即可而且也记不住一般只需要掌握Path这种路由工程就可以了 总结 PredicateFactory的作用是什么 读取用户定义的断言条件对请求做出判断 Path/user/**是什么含义 路径是以/user开头的就认为是符合的 过滤器工厂 GatewayFilter是网关中提供的一种过滤器可以对进入网关的请求和微服务返回的响应做处理 路由过滤器的种类 Spring提供了31种不同的路由过滤器工厂。下面是几种常见的过滤器 名称说明AddRequestHeader给当前请求添加一个请求头RemoveRequestHeader移除请求中的一个请求头AddResponseHeader给响应结果中添加一个响应头RemoveResponseHeader从响应结果中移除有一个响应头RequestRateLimiter限制请求的流量 这里以请求投过滤器为例来写个案例示范 需求给所有进入userservice的请求添加一个请求头Hello World 只需要修改gateway服务的application.yml文件添加路由过滤即可 spring:cloud:gateway:routes:- id: user-service uri: lb://userservice predicates: - Path/user/** filters: # 过滤器- AddRequestHeaderHead, Hello World # 添加请求头测试效果 结果如下 默认过滤器 上面加的过滤器是只针对对应的路由有效若要像对所有路由都有效就可以配置默认过滤器 如果要对所有的路由都生效则可以将过滤器工厂写到default下 spring:cloud:gateway:routes:- id: user-service uri: lb://userservice predicates: - Path/user/**default-filters: # 默认过滤项- AddRequestHeaderHead, Hello World 总结 过滤器的作用是什么 ① 对路由的请求或响应做加工处理比如添加请求头 ② 配置在路由下的过滤器只对当前路由的请求生效 defaultFilters的作用是什么 对所有路由都生效的过滤器 全局过滤器 虽然默认过滤器已经实现了全局过滤路由的功能了但是不能自定义无法进行定制过滤 全局过滤器的作用也是处理一切进入网关的请求和微服务响应与GatewayFilter的作用一样。区别在于GatewayFilter通过配置定义处理逻辑是固定的而GlobalFilter的逻辑需要自己写代码实现。 定义方式是实现GlobalFilter接口。 在filter中编写自定义逻辑可以实现下列功能 登录状态判断权限校验请求限流等 自定义全局过滤器 范例 需求定义全局过滤器拦截请求判断请求的参数是否满足下面条件 参数中是否有authorization authorization参数值是否为admin 如果同时满足则放行否则拦截 在gateway中定义一个过滤器 这个Order(-1)是指定过滤器执行的顺序比如有很多过滤器时这个就是指定谁先执行谁后执行值越小越先执行 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的顺序执行。 跨域问题 跨域域名不一致就是跨域主要包括 域名不同 www.taobao.com 和 www.taobao.org 和 www.jd.com 和 miaosha.jd.com 域名相同端口不同localhost:8080和localhost8081 跨域问题浏览器禁止请求的发起者与服务端发生跨域ajax请求请求被浏览器拦截的问题 解决方案CORS CORS详解 解决跨域问题 在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 # 这次跨域检测的有效期未完待续 受篇幅限制微服务的剩余组件DockerMQES的使用及解析在下篇继续记录。感谢您的阅览
http://www.dnsts.com.cn/news/153426.html

相关文章:

  • 网站标题title为什么不能频繁的改上海建交人才网官网
  • 阅读分享网站模板旅游网站建设哪家好
  • 网站如何做关键字收录wordpress jet插件
  • 无锡网络公司无锡网站设计给金融公司群做网站合法吗
  • 网站建设首选公司哪家好连云港网页设计
  • 网站的关键词排名外贸网站设计与推广
  • 全球设计网分站上海短视频培训机构
  • 深圳惠州网站建设公司潍坊科技学院
  • 电子商务网站建设移动电商开发东莞p2p网站开发费用
  • 废旧网站哪个做的最好世界知名网站
  • 公司门户网站什么意思花都网站设计
  • 实训课建设网站步骤汕头第一网e京网
  • 怎么做网站弹窗建网站代理
  • 焦作网站建设公司排名wordpress 音乐电台
  • 工信部信息备案网站做网站和app多少费用
  • 企业做网站需要花多少钱哪些网站可以做招生信息
  • 龙岗建网站竞价托管公司
  • 建设网站申请空间需要多少钱建网站被封了
  • 家具东莞网站建设0769wordpress 字数插件
  • 天津武清做网站网站建设分为哪几种
  • 公司设计网站定制wordpress列表框内显示标题
  • wordpress库存插件处理器优化软件
  • 商业网站台州椒江区热销企业网站搭建
  • 嘉定江桥网站建设入门级网页设计培训学员
  • 上海做网站比较有名的公司有哪些wordpress 后台速度慢
  • 婚恋网站开发背景文献网站 域名 授权服务器 分布式
  • 东莞网站设计公司有哪些企业网站提交
  • 云建设网站洛可可设计集团
  • 江阴建设网站德惠市城乡建设局网站
  • 建设单位企业锁登陆网站企业解决方案有哪些