实战pringloud大码哥

部署环境:阿里云ECS服务器

端口映射信息:

eureka1:8761 | eureka2:8762

config-server:8888

shopping-product:11100

shopping-order:11110

api-gateway:8080

open-api:8081

因为Module作为子项目,我们改写下对应的POM文件。

重新Build一下项目,能正常编译。但是此时Eureka Server是不能正常启动工作的,需要在application类增加

@EnableEurekaServer。

同样,我们修改POM文件,依赖于父项目,注意这里需要引入eureka-client和spring-boot-starter-web依赖。

需要在application类增加@EnableDiscoveryClient,同时修改配置文件。

重启Eureka Client,启动后再次访问Eureka Server管理界面,可以发现order-provider服务已注册。

之前我们的Eureka Server是单点服务,实际生产中,经常是多台注册中心,因此我们尝试下配置2台注册中心。

启动服务器实例1:

启动服务器实例2:

重启2台注册中心,启动后分别访问2台的管理界面,可以看到2台注册中心已经相互注册。

项目增加2个服务模块,并向Eureka Server注册:shopping-product(商品服务)、shopping-order(订单服务),实现相应业务逻辑,这部分详细实现不再阐述。

整体项目结构如下:

spring-cloud-app

​ --eureka-server(服务注册中心)

​ --shopping-common(购物公共模块)

​ --shopping-product(商品服务模块)

​ --shopping-order(订单服务模块)

系统架构如图,比较简单,一个集群服务中心,目前有2个服务提供并注册:

Spring Cloud Ribbon 是一个客户端的负载均衡器,它提供对大量的HTTP和TCP客户端的访问控制。

客户端负载均衡即是当浏览器向后台发出请求的时候,客户端会向 Eureka Server 读取注册到服务器的可用服务信息列表,然后根据设定的负载均衡策略(没有设置即用默认的),抉择出向哪台服务器发送请求。

假设有以下业务场景,shopping-order模块需要调用shopping-product提供的API接口。我们看如何实现。

第一种方法使用构造RestTemplate,调用远程API,这种方法url是写死,如果启动多台shopping-product服务的话,那又该如何?

第二种方法:我们启动2个shopping-product服务实例,分别是11100端口和9001端口,运行测试发现,会根据loadBalancerClient负载均衡机制帮我们选择一个服务地址,进行访问调用。

但这样依旧很是麻烦,接下来看第三种方法。第三种方法屏蔽了API的具体url信息,只用ServerId,并根据负载均衡规则,自动路由到对应的地址。

因为eureka包中已经添加了对Ribbon的依赖,我们可以增加断点,调试程序,发现进入RibbonLoadBalancerClient-->choose方法,返回负载均衡策略选择的ServiceInstance。

当然,我们也可以指定应用服务的负载均衡策略:

目前系统架构如图,实现shopping-product和shopping-order集群化部署,调用方式通过客户端负载均衡,来路由消费端的请求。

Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。

而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Feign整合了Ribbon和Hystrix(关于Hystrix我们后面再讲),可以让我们不再需要显式地使用这两个组件。

总起来说,Feign具有如下特性:

shopping-product服务提供端暴露API。

shopping-order模块需要调用shopping-product接口,首先我们在服务调用端增加Maven依赖

启动类标注开启Feign服务

本地调用测试,可以正常返回接口数据。

上个环境中,我们有2个服务提供者,首先看下各自的配置,可以发现很大一部分都是重复的。

如果微服务架构中没有使用统一配置中心时,所存在的问题:

Spring Cloud Config 有它的一套访问规则,我们通过这套规则在浏览器上直接访问就可以。

{application} 就是应用名称,对应到配置文件上来,就是配置文件的名称部分,例如我上面创建的配置文件。

{label} 表示 git 分支,默认是 master 分支,如果项目是以分支做区分也是可以的,那就可以通过不同的 label 来控制访问不同的配置文件了。

config-server本身作为一个服务,也可以作为服务提供方,向服务中心注册,其他的服务想要获取配置文件,只需要通过服务名称就会访问。

Spring Cloud Config 在项目启动时加载配置内容这一机制,但是如果我们修改配置文件内容后,不会自动刷新。例如我们上面的项目,当服务已经启动的时候,去修改 github 上的配置文件内容,这时候,再次刷新页面,对不起,还是旧的配置内容,新内容不会主动刷新过来。那应该怎么去触发配置信息的动态刷新呢?

它提供了一个刷新机制,但是需要我们主动触发。那就是 @RefreshScope 注解并结合 actuator ,注意要引入 spring-boot-starter-actuator 包。

每次改了配置后,就用 postman 访问一下 refresh 接口,还是不够方便。 github 提供了一种 webhook 的方式,当有代码变更的时候,会调用我们设置的地址,来实现我们想达到的目的。

填上回调的地址

也就是上面提到的 actuator/refresh 这个地址,但是必须保证这个地址是可以被 github 访问到的。这样每当github上修改了配置文件,就自动通知对应的hook地址自动刷新。

整体项目结构如下:

spring-cloud-app

​ --config-server(统一配置中心)

​ --eureka-server(服务注册中心)

​ --shopping-common(购物公共模块)

​ --shopping-product(商品服务模块)

​ --shopping-order(订单服务模块)

1、异步处理

比如用户在电商网站下单,下单完成后会给用户推送短信或邮件,发短信和邮件的过程就可以异步完成。因为下单付款是核心业务,发邮件和短信并不属于核心功能,并且可能耗时较长,所以针对这种业务场景可以选择先放到消息队列中,有其他服务来异步处理。

2、应用解耦:

假设公司有几个不同的系统,各系统在某些业务有联动关系,比如 A 系统完成了某些操作,需要触发 B 系统及 C 系统。如果 A 系统完成操作,主动调用 B 系统的接口或 C 系统的接口,可以完成功能,但是各个系统之间就产生了耦合。用消息中间件就可以完成解耦,当 A 系统完成操作将数据放进消息队列,B 和 C 系统去订阅消息就可以了。这样各系统只要约定好消息的格式就好了。

3、流量削峰

比如秒杀活动,一下子进来好多请求,有的服务可能承受不住瞬时高并发而崩溃,所以针对这种瞬时高并发的场景,在中间加一层消息队列,把请求先入队列,然后再把队列中的请求平滑的推送给服务,或者让服务去队列拉取。

4、日志处理

kafka 最开始就是专门为了处理日志产生的。

当碰到上面的几种情况的时候,就要考虑用消息队列了。如果你碰巧使用的是 RabbitMQ 或者 kafka ,而且同样也是在使用 Spring Cloud ,那可以考虑下用 Spring Cloud Stream。Spring Cloud Stream 是消息中间件组件,它集成了 kafka 和 rabbitmq ,本文以rabbitmq 为例。

分析目前shopping-order项目中,创建订单的代码如下:

创建订单的同时,先调用商品接口扣减库存,如果占用库存成功,再生成订单。这样的话,生成订单的操作和占用商品库存的操作其实是耦合在一起的。在实际电商高并发、高流量的情况下,我们很少这么做。所以,我们要将业务解耦,实现订单和扣减库存的异步处理。

大体思路如下:生成订单==》通知商品调用库存==》商品占用库存==》通知订单占用成功==》更新订单占用库存状态

shopping-order、shopping-product项目中

启动应用程序,测试发送接口,发现spring-cloud-stream帮我们自动创建了一个队列,消息发送到这个队列,然后被接收端消费。

shopping-order作为库存占用命令的消息发送者,首先向shopping-product发送消息stock_apply(占用库存申请),shopping-product接收此消息进行库存处理,然后将库存占用处理的结果作为消息stock_result(占用库存结果)发送,shopping-order端再收到结果消息对订单状态进行更新。

执行调试结果,跟踪执行结果:生成订单同时发送库存申请命令,商品模块处理库存申请成功后,返回库存占用结果告知订单模块,从而实现订单生成和商品库存占用的逻辑的解耦。

在原有的架构基础上,我们对商品和订单服务进行了应用解耦,库存占用逻辑异步化,通过消息队列传递消息,并结合spring cloud stream对消息input和output绑定,使得在程序中很方便的进行消息发送和接收处理。

zuul的核心是一系列的filters, 其作用类比Servlet框架的Filter,或者AOP。zuul把请求路由到用户处理逻辑的过程中,这些filter参与一些过滤处理,比如Authentication,Load Shedding等

Zuul使用一系列不同类型的过滤器,使我们能够快速灵活地将功能应用于我们的边缘服务。这些过滤器可帮助我们执行以下功能:

默认的路由规则是按照服务的名称来路由服务,当然我们也可以自定义。在zuul中,路由匹配的路径表达式采用ant风格定义

这样我们再访问这个接口时,就提示 Not Found 错误了

之前路由的配置都是写在配置文件中,如果路由规则变化以后,需要重启网关服务。但是实际生产环境,一般都需要动态的加载路由的配置,不能轻易重启网关服务。

设想以下场景:我们需要判断用户请求的参数是否包含认证信息,如果包含token信息,则可以访问,否则禁止访问。可以用Zuul Filter很方便的实现在网关端,统一进行认证。

这里介绍一种限流的设计方案:

对于很多应用场景来说,除了要求能够限制数据的平均传输速率外,还要求允许某种程度的突发传输。这时候漏桶算法可能就不合适了,令牌桶算法更为适合。如图所示,令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

Google公司已经实现了上述的令牌桶的算法,直接使用 RateLimiter 就可以通过Zuul实现限流的功能:

整体项目结构如下:

spring-cloud-app

​ --api-gateway(服务网关)

​ --config-server(统一配置中心)

​ --eureka-server(服务注册中心)

​ --shopping-common(购物公共模块)

​ --shopping-product(商品服务模块)

​ --shopping-order(订单服务模块)

目前所有的客户端请求,首先被发送到统一网关服务处理,然后由网关进行限流、熔断、权限验证、记录日志等等,然后根据自定义的路由规则,再分发到不同的应用服务中去,应用服务器返回处理结果后,由网关统一返回给客户端。

在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。

更恐怖的是,如果这是一个多级调用,即此处的服务的调用结果还被其他服务调用了,这就形成了所谓的雪崩效应,后果将不堪设想。因此,需要某种机制,在一定的异常接口调用出现的时候,能够自动发现这种异常,并快速进行服务降级。

这样的话,shopping-order调用远程服务,超过3s之后,立刻返回错误处理,不会再阻塞。

如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。

Spring Coud 还给 Hytrix 提供了一个可视化的组件:

通过以上容错方法的实现,就可以构建更加稳定、可靠的分布式系统:

微服务架构是一个分布式架构,它按业务划分服务单元,一个分布式系统往往有很多个服务单元。由于服务单元数量众多,业务的复杂性,如果出现了错误和异常,很难去定位。主要体现在,一个请求可能需要调用很多个服务,而内部服务的调用复杂性,决定了问题难以定位。所以微服务架构中,必须实现分布式链路追踪,去跟进一个请求到底有哪些服务参与,参与的顺序又是怎样的,从而达到每个请求的步骤清晰可见,出了问题,很快定位。

OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库和追踪或日志分析程序之间。

OpenTracing 的优势

OpenTracing 数据模型

OpenTracing 中的 Trace(调用链)通过归属于此调用链的 Span 来隐性的定义。特别说明,一条 Trace(调用链)可以被认为是一个由多个 Span 组成的有向无环图(DAG图),Span 与 Span 的关系被命名为 References。

例如:下面的示例 Trace 就是由8个 Span 组成:

每个 Span 包含以下的状态:(译者注:由于这些状态会反映在 OpenTracing API 中,所以会保留部分英文说明)

键值对中,键必须为 string,值可以是任意类型。但是需要注意,不是所有的支持 OpenTracing 的 Tracer,都需要支持所有的值类型。

每一个 SpanContext 包含以下状态:

OpenTracing 实现

事件类型

Zipkin Server主要包括四个模块:

Collector 接收或收集各应用传输的数据

Storage 存储接受或收集过来的数据,当前支持Memory,MySQL,Cassandra,ElasticSearch等,默认存储在内存中。

API(Query) 负责查询Storage中存储的数据,提供简单的JSON API获取数据,主要提供给web UI使用

Web 提供简单的web界面

首先,安装 zipkin,为了方便直接用 docker 进行安装,具体详见容器化部署章节,这里不再详述。

在服务调用的过程中,通过Sleuth将链路信息(经过抽样后的信息)统一上报给Zipkin,通过Zipkin就可以集中查看和管理微服务架构中的调用链路信息,便于开发人员与运维人员跟踪和调试问题。

-management 表示有管理界面的,可以浏览器访问。5672是访问端口,15672是管理端口。

THE END
0.海灵顿公爵最新章节免费阅读全本目录更新无删减第八十一章 龙卷风摧毁停车场 第八十二章 正经的巨龙 第八十三章 慈眉善目的泰德 第八十四章 包吃包住! 第八十五章 税收 第八十六章 为了主人! 第八十七章 黑色液体! 第八十八章 好戏开场了! 第八十九章 30mm的狙击炮 第九十章 打!龙! 第九十一章 黑龙心脏 第九十二章 秩序的重要性! 第jvzquC41yy}/smro0eun1lfvcnuh1:5558?59<:1
1.龙卷风摧毁停车场龙卷风摧毁停车场是一个引人关注的现象。 在动画《成龙历险记》中黑虎阿福的这一招式因其独特的名称和强大的威力让人印象深刻。 现实中龙卷风也会带来严重破坏。比如在山东省菏泽市东明县7 月 5 日疑似出现的龙卷风移动速度极快卷起大量碎片并伴有闪电对当地造成一定程度的破坏当地气象台已发布强对流橙色预警。 龙卷jvzquC41o0vdc~yq0eun0ls1ygtec89288>967mvon
2.《海灵顿公爵》小说在线阅读第八十一章 龙卷风摧毁停车场 第八十二章 正经的巨龙 第八十三章 慈眉善目的泰德 第八十四章 包吃包住! 第八十五章 税收 第八十六章 为了主人! 第八十七章 黑色液体! 第八十八章 好戏开场了! 第八十九章 30mm的狙击炮 第九十章 打!龙! 第九十一章 黑龙心脏 第九十二章 秩序的重要性! 第jvzquC41yy}/smro0eun1ktqm1715<;;69961
3.奥特曼任意键:启明最新章节奥特曼任意键:启明说的道理82 特利迦体验卡已加更求追读 83 打过来我第一个跑 84 盖亚 这次真得破坏大地了求追读 85 龙卷风摧毁停车场 86 抽到了格利扎 87 原子弹再度落入日本 88 希卡利现身 89 破灭招来体也干了 90 天界VS台风怪兽 下卷预告上架感言 91 虫洞出现求首订 92 对话藤宫希卡利对战博伽茹 93 钢铁侠行为查看更多章节 jvzquC41yy}/sz}uy0rb1ktqma86;:771
4.流云:“你猜我为什去辅助?”闲执法4.4双通龙卷风摧毁停车场如果魈不玩玉米队,把流云换成班尼特或者带满精苍古的四命琴,一次下落没有流云珐露珊双人组单段伤害高,以上都是用满配测的,流云换个爆伤头差距就更大了 魈用的满精息灾,最多扎过42万,算擦伤50万出头,流云这里只换了爆伤头其他的圣遗物没动。就有60万了,而且流云不会断充能。不过魈的攻击频率高2个jvzquC41yy}/or~qwunf0lto1dn31jwvkerf1=>5:8;39
5.神王在人间送外卖的日子完整版在线免费阅读第45章 龙卷风摧毁停车场 第46章 捍卫外卖员的尊严 第47章 婚礼闹剧 第48章 生命套装出现 第49章 索长风觉醒,剑指动物园 第50章 一窝端了吴三爷势力 第51章 对头要找来了 第52章 欲捉克苏鲁甲虫 第53章 教唆曹老板当黑老大 第54章 李三平终于觉醒 第55章 要不给哪吒找个女朋友? 第56章 谋划福报寺jvzquC41hctrknsqxgr/exr1rcmf1@9:89925=:758=76B:5
6.2012年8月22日随笔档案龙卷风摧毁停车场!摘要: 页面A利用window.open方法弹出页面B,页面A所在的窗口就是页面B的opener,可以通过页面B的opener对象访问页面页面A利用iframe或frame调用B页面,那么页面A所在窗口就是B页面的parent。即父窗口阅读全文 posted @ 2012-08-22 10:37 龙卷风摧毁停车场!阅读(193)评论(0)推荐(0) jvzquC41yy}/ewgnqiy/exr1hjwrmzupwko0c{hjkxk0496412>04;3jvor