首页 > Microservice

说起Feign,那又是老东西了啊

我以前写Netfilx的时候就详细讲过Feign这玩意,其实用起来基本是一样的。

以前的文章地址 : 分布式微服务项目如何使用 Feign 实现声明式 REST 调用,以及自定义 Feign 配置

 

虽说切换到了Alibaba,但是也没啥变化,Feign该怎么用就怎么用,这就不详细说了。主要还是Sentinel

其实Sentinel 和Hystrix在代码里写起来也是一样的

首先肯定是要上pom.xml配置起来。加上对应的依赖。

 

接着写个Feign接口

调用的话就是这样子调用:

 

哎,观察我的NacosHelloFeign类,这里可以看到,我这用了一个fallback回退,这个回退指定的就是Sentinel 的实现,其实写起来和特么的Hystrix一模一样。不得不说SpringCloud这一点是真的做得好。

 

当然,配置肯定是得配置的,他也不会直接就给你用了。

Sentinel 虽说是适配了 Feign 组件。但默认是关闭的。需要在配置文件中配置打开它,在配置文件增加以下代码:

 

其实到现在,整个Feign的使用+熔断限流机制就已经配完了。

不过Sentinel 比起Hystrix真正优越的地方还没来呢。

那就是: 控制台

这个控制台功能丰富、UI好看,比Hystrix那是高到不知道哪里去了。

要是用控制台,又不得不下载代码、打包、编译、运行。

 

所幸,我们有神器docker。我在docker hub 上找了个镜像,直接用就可以了,镜像地址:https://hub.docker.com/r/bladex/sentinel-dashboard

直接执以下命令,将sentinel控制台起开绑到8858端口

 

然后自己的yml文件也得改一下,毕竟都上控制台了,也得把自己这个服务给注册进去。

全部的yml文件如下所示:

可以看到配置里有一个 sentinel.transport.port属性,这个属性的意思是在自己本体这个服务里边,在开个新的端口专门用来和 Sentinel 控制台交互

Sentinel 控制台自身也有,默认端口则是8719

 

到这里就差不多了,所有东西打开,然后就可以访问 http://ip:8858 进入Sentinel 控制台,默认账号密码都是sentinel

有一点还需要注意,那就是为了确保客户端有访问量,Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。意思就是说你一个服务注册进我这来,首先还是看不到的。

你得先经过别人的请求,我才会去监控你,所以在服务刚启动的时候进入Sentinel 控制台找不到自己的服务是很正常的,只要启动时没有报错就不会有问题。

 

 

阅读全文

 

中秋佳节当天,人在异乡,无法和家人团聚,既然如此 不如提升一波自己的姿势水平,免得浪费这假期大好光阴。

说道微服务,现在可不流行Netfilx那一套了, 现在都9102年9月了,Spring Cloud Aliabba都已经孵化完毕,再加上Netfilx将他旗下的项目通通打入冷宫,现在在不学习SpringCloudAlibaba体系就赶不上时代的潮流了。 Netfilx那套体系我都搭过demo 写过博客,各种配置啊注意点啊都挺详细的,感兴趣的可以翻我以前的文章。

 

 

https://github.com/alibaba/spring-cloud-alibaba 这是 SpringCloudAlibaba 的项目 git。

这篇文章主要是开个SpringCloudAliabba篇的头,正式开始SpringCloudAlibaba的学习。

 

 

废话不多说,进入正题。

今天就从微服务最重要的地方开始,当然,也只能从这个地方开始。

那就是服务治理。

 

在 Spring Cloud Netflix 使用的是Eureka,而SpringCloudAlibaba 给我们提供的就是Nacos。

而且,Nacos比Eureka 更加强大,他还可以用来当配置中心。

 

这里我就简单的先完成他基本的职责:服务注册与发现。

首先nacos和Eureka有点不同。

他这个应用。不是我们自己写的,Eureka这个东西他需要我们自己创建一个应用。然后在编写代码,然后再将项目打包,在启动。

Nacos这个东西他和Zipkin有点像,是那种直接下载下来运行就完事了的。

 

我这儿用Docker来运行一个单机的 Nacos 镜像添加到8848端口(默认端口),当然,集群是肯定可以集群的,我这先不玩。

对了,不知道为啥我用网易的docker镜像地址下载会卡住,之后换了alibaba的来下就没问题了。

nacos登陆地址:http://ip:8848/nacos   默认账号密码是nacos/nacos

 

开启Nacos服务完毕后,就要开始写服务提供者和服务消费者了。

其实这俩都差不多,反正注册进服务治理中心了,A可以调用B的服务,自然B也可以调用A的服务,导入的配置也一样,我这就以服务消费者来举例子,避免贴两份基本相同的代码了。

 

我这使用的是最新的版本,要用就用最新的,不然没意思。我之前写的Netflix项目也是使用的最新的,当时用的是SpringCloud F版第三版

现在这个项目用的是SpringCloud G版第三版,SpringBoot 2.1.8.RELEASE

 

先创个依赖项目进行最基本的统一依赖管理

 

这个项目集成了SpringBoot 然后导入了SpringCloud的依赖和SpringCloudAlibaba的依赖。

依赖项目写完之后就是正式开工编写服务。

这个服务就直接继承我刚刚写的依赖项目就可以了。

 

然后在其中,引入web、actuator、test几个SpringBoot依赖。当然还有必不可少的SpringCloudAlibaba Nacos 依赖。

启动类:

 

这个启动类用了个 @EnableDiscoveryClient 这个注解,该注解是SpringCloud内置的,Nacos实现了这个注解,导入了Nacos的依赖的话就代表要注册进Nacos里边。

这样的好处就是以后要是换个新的服务治理中心,代码都不用改就可以轻易的更换,完美符合里式替换原则

 

 

既然能注册进去了,那接着还是老规矩,来个RestTemplate进行远程服务的调用,@LoadBalanced代表负载均衡,这些东西我以前的文章都有讲过啊,这儿就不详细说了。

 

这里就是编写一个控制层,来进行接口对外暴露,内部就是使用RestTemplate+LoadBalancerClient 来进行负载均衡的调用其他服务。

 

当然,yml是肯定要写的。

 

对了,这个management.endpoints 下边端点一定得打开。

因为 SpringCloudAlibaba 的 Nacos 在实现的时候提供了一个 EndPoint, EndPoint 的访问地址为 http://ip:port/actuator/nacos-discovery。

这玩意和服务注册发现息息相关,要是Nacos访问不了这个端点,那你就注册不了。

 

其实到这就差不多了,服务已经可以注册进Nacos里了,然后微服务之间的互相调用也是没有问题的,负载均衡也可以实现。

都没啥好说的,只要学会SpringCloud的思想,组件从一套换成另一套也就几十分钟的时间。

阅读全文

Zookeeper 是一种分布式协调服务,在分布式环境中协调和管理服务是一个复杂的过程。ZooKeeper 通过其简单的架构和 API 解决了这个问题。ZooKeeper 允许开发人员专注于核心应用程序逻辑,而不必担心应用程序的分布式特性。

 

分布式协调服务主要用来解决分布式环境当中多个进程之间的同步控制,让他们有序的去访问某种临界资源,防止造成”脏数据”的后果。

为了防止分布式系统中的多个进程之间相互干扰,需要一种分布式协调技术来对这些进程进行调度。

而这个分布式协调技术的核心就是来实现这个分布式锁。

 

分布式锁应该具备哪些条件?

1、在分布式系统环境下,一段代码在同一时间只能被一个机器的一个线程执行

2、高可用的获取锁与释放锁

3、高性能的获取锁与释放锁

4、具备可重入特性(可理解为重新进入,由多于一个任务并发使用,而不必担心数据错误)

5、具备锁失效机制,防止死锁

6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败

 

关于业界比较流行的分布式锁实现方案:

一般来说Redis会经常被提及到,但是Redis并不是天生为了实现分布式锁而设计出来的, 他是个NoSql内存数据库;不过我们可以利用一些Redis的特性来实现 分布式锁 这个需求

这个链接文章比较清晰的说了redis如何实现分布式锁和redis分布式锁面临的问题,这个说的很清楚了我就不详细说了。

http://zhangtielei.com/posts/blog-redlock-reasoning.html

 

那Zookeeper呢 ,雅虎工程师设计Zookeeper的初衷,就是为了实现分布式锁服务的,利用 Zookeeper 的顺序临时节点,来实现分布式锁和等待队列。当然Zookeeper不止这个功能,比如它可以用来实现服务发现与注册的功能,单以这个需求来使用Zookeeper的也是很多的。

 

在说Zookeeper实现分布式锁之前,首先来讲下他为啥可以实现分布式锁,以及Zookeeper的数据模型:

Zookeeper 的数据模型很像数据结构当中的树,也很像文件系统的目录。

树是由节点所组成,Zookeeper 的数据存储也同样是基于节点,这种节点叫做 Znode,但是,不同于树的节点,Znode 的引用方式是路径引用,类似于文件路径:/car/bmw   、/animal/cat

这样的层级结构,让每一个 Znode 节点拥有唯一的路径。

 

那么Znode 包含哪些元素呢?有这么些:

  • data:Znode 存储的数据信息。
  • ACL:记录 Znode 的访问权限,即哪些人或哪些 IP 可以访问本节点。
  • stat:包含 Znode 的各种元数据,比如事务 ID、版本号、时间戳、大小等等。
  • child:当前节点的子节点引用

Zookeeper 是为读多写少的场景所设计。Znode 并不是用来存储大规模业务数据,而是用于存储少量的状态和配置信息,每个节点数据最大只有1M。

关于Zookeeper的基本增删改查的操作就不详细说明了,主要有这么几种:create、delete、exists、getData、setData、getChildren。

而跟增删改查息息相关的,Zookeeper 客户端在请求读操作的时候,可以选择是否设置 Watch,也就是Zookeeper的事件通知机制

 

可以把 Watch 理解成是注册在特定 Znode 上的触发器。调用了 create、delete、setData 方法的时候 (做出修改操作时),将会触发 Znode 上注册的事件,请求 Watch 的客户端会接收到异步通知。

大概的事件通知机制如下:

  • 客户端调用 getData 方法,watch 参数是 true。服务端接到请求,返回节点数据,并且在对应的哈希表里插入被 Watch 的 Znode 路径,以及 Watcher 列表。
  • 当被 Watch 的 Znode 已删除,服务端会查找哈希表,找到该 Znode 对应的所有 Watcher,异步通知客户端,并且删除哈希表中对应的 Key-Value。

 

好,说了这么多,差不过该进入主题如何实现分布式锁了,上边说了利用 Zookeeper 的顺序临时节点可以实现分布式锁,那么这顺序临时节点又是个什么玩意?

默认创建的Znode  是”持久节点” 创建节点的客户端与 Zookeeper 断开连接后,该节点依旧存在。

除此之外,还有其他几种,其实看名字也能猜出是啥用了:

持久顺序节点:  所谓持久顺序节点,就是在创建节点时,Zookeeper 根据创建的时间顺序给该节点名称进行编号。其他和持久节点一样。

临时节点:  和持久节点相反,当创建节点的客户端与 Zookeeper 断开连接后,临时节点会被删除。

临时顺序节点: 顾名思义,临时节点和顺序节点的合成体;在创建节点时,Zookeeper 根据创建的时间顺序给该节点名称进行编号;当创建节点的客户端与 Zookeeper 断开连接后,节点会被删除。

 

Zookeeper 分布式锁的原理机制:

说完节点,也就差不多可以实现分布式锁了,其实知道这几个节点是个什么玩意后,在结合一下Watch机制,基本可以在脑内猜想个实现大概出来。

加锁释放锁流程:

1、首先,在 Zookeeper 当中创建一个持久节点,给它取个名字名字叫 ParentLock。当第一个客户端想要获得锁时,在 ParentLock 这个节点下面创建一个临时顺序节点 Lock1。之后,Client1 查找 ParentLock 下面所有的临时顺序节点并排序,判断自己所创建的节点 Lock1 是不是顺序最靠前的一个。如果是第一个节点,则成功获得锁。

2、这时候,如果再有一个客户端 Client2 前来获取锁,则在 ParentLock 下再创建一个临时顺序节点 Lock2。

3、Client2 查找 ParentLock 下面所有的临时顺序节点并排序,判断自己所创建的节点 Lock2 是不是顺序最靠前的一个,结果发现节点 Lock2 并不是最小的。于是,Client2 向排序仅比它靠前的节点 Lock1 注册 Watcher,用于监听 Lock1 节点是否存在。这意味着 Client2 抢锁失败,进入了等待状态,这就形成了一个等待队列。

4、  当任务完成时,Client1 会显示调用删除节点 Lock1 的指令。此时由于 Client2 一直监听着 Lock1 的存在状态,当 Lock1 节点被删除,Client2 会立刻收到通知。这时候 Client2 会再次查询 ParentLock 下面的所有节点,确认自己创建的节点 Lock2 是不是目前最小的节点。如果是最小,则 Client2 顺理成章获得了锁。

5、如果说获得锁的 Client1 在任务执行过程中如果崩溃了,则会断开与 Zookeeper 服务端的链接。根据临时节点的特性,相关联的节点 Lock1 会随之自动删除;所以Client2 又收到通知获得了锁。

 

说到这,是不是觉得Zookeeper的机制来实现分布式锁较为不错,人家都给你封装好了,不用向Redis那样实现分布式锁还得考虑超时、原子性、误删除之类的。

还有等待队列可以提升抢锁效率,比起Redis实现的效果确实是舒服了许多。

 

阅读全文

说是简单,tm那是找到解决方案之后才简单。

可能是我用的SpringCloud版本太新了,自己配zipkin server把我给配吐了。

又是版本冲突、又是注册不进去Eureka、又是访问ui报错、又是找不到ObjectProvider.orderedStream()方法的,我从百度搜到必应搜到google搜到Stack Overflow,整了一个上午。

我就想着,这玩意怎么能这么恶心呢?感觉像写maven的时候狂报xml错误那种感觉。

 

后来怼到zipkin官网 zipkin.io 上去,卧槽,快速入门里有这么句话:

If you have Java 8 or higher installed, the quickest way to get started is to fetch the latest release as a self-contained executable jar:

 

 

我佛了。然后又查了些关于高版本资料,关于 Zipkin 的服务端,在使用 Spring Boot 2.x 版本后,官方就不推荐自行定制编译了,反而是直接提供了编译好的 jar 包来给我们使用,这是官方提供的演示: https://github.com/openzipkin/docker-zipkin

白搞了半天,原来只要自己去下他的jar包然后启动这个服务就行了,至于如何将微服务跟踪的数据存到mysql/kafka/es 里边去,也可以直接用启动参数指定。

那我还自己配个蛇皮的zipkin server。

 

可以去这个网址: https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/ 选择下载zipkin的各个不同版本的启动jar,我随便找了一个,启动很顺畅,进入 localhost:9411 可以访问ui。

那服务端就算这样配完了,全部流程: 下载 –> 使用 java -jar 命令运行下载的jar

 

服务端搞完后,就到客户端了。

微服务链路跟踪嘛,需要得到请求经过了哪些微服务,了解请求流转的具体参数,那么客户端自然就是一个个不同的微服务了。

 

以我之前的user微服务为例,配置都一样。

build.gradle中加上这一行:

本来应该是spring-cloud-starter-sleuth,spring-cloud-sleuth-zipkin这两个依赖,但是spring-cloud-starter-zipkin这个集成了前面那俩,和前面那俩依赖效果是一样的。

加完依赖后只需要指定zipkin服务地址就好了

我的applicayion.yml:

 

spring.zipkin.base-url 指定地址。zipkin端口号默认9411。

spring.sleuth.sampler.probability 设置采样百分比,采样百分比就是会按比例来跟踪/保存多少条请求数据,因为在线上运行的话那数据是相当庞大的。默认设置的是0.1,也就是百分之十,我这设置百分之百是为了本地调试。

 

然后就完事了

对,没问题。所有微服务开起来,Eureka、Zuul等等,当然还有Zipkin官方服务。网页请求几个API,再去 localhost:9411 刷新一下,就可以看到每一条请求的详细信息了。

 

实现微服务跟踪需要的步骤:

1、 下载官方推荐的jar包

2、运行起来

3、改下微服务,加个依赖加个配置

完事了,如果想要保存数据到es/mysql/kafka里分析,可以设置启动参数,具体可以去看官方、github

 

 

我的使用Gradle搭的SpringCloud Finchley.SR3 项目整体地址:

https://github.com/skypyb/codeDemo/tree/master/sc-demo-microservice

阅读全文

上篇文章主要是搭建了一下Zuul的服务,并且实现了Zuul过滤器的自定义需求。

里边讲到了,Zuul 已经集成了 Ribbon、Hystrix ; 而 Ribbon无需配置,会在请求路由时自动给你进行负载均衡。

但是在Zuul服务路由不到对应微服务时,是没有对应的回退机制的,还是得自己手动写一下。

 

实现路由失败回退机制,首先需要继承 FallbackProvider 类,实现其getRoute() 和 fallbackResponse() 方法。

getRoute方法是指定你需要回退的线路,返回一个服务名就行。它会在路由该服务发生故障时调用 fallbackResponse 方法从而返回你一个 ClientHttpResponse 对象。

 

我写的回退代码:

 

 

这个代码会在路由到sc-demo-microservice-user这个服务出错时触发,然后根据不同的异常给出不同的响应(我这就是变了个Status哈)

配上一个回退机制后,就让Zuul服务更加完善健壮了,这样子,就算路由的服务挂掉了,我也能返回个东西让前端显示,也能做一些其余的抢救操作。

 

Zuul这个服务到这,其实也就差不多了,该有的都有,虽说也有Zuul这个服务挂掉的可能,但是Zuul也是可以集群的呀,前端可以访问一个负载均衡的服务器(比如Nginx),让他来转发请求到集群Zuul服务上边,这样子,整个微服务架构就非常健壮了(像这种Nginx服务一般不会挂哈,就一个纯走流量的服务器都能挂了,那你的流量是有多猛   除非硬件问题,那没辙)

 

咳咳, 说起来Zuul服务搭是搭好了,但是你就做一个服务路由+负载均衡,那也不是个事啊,我客户端那边请求服务,我要是需要多个数据,我是不是要发多个请求?

每个请求都要走–>zuul–>service 这一套流程,是不是不大好,毕竟我发多个请求来请求多个服务,总会有性能损耗。

那要是我就发一个请求到Zuul Server ,然后由Zuul 来帮我聚合请求多个微服务,包装成一个数据返回响应给我好不好鸭,那当然是极好的。这些微服务所在的服务器八成是在一个局域网里(除非你买的实例所在地区不同甚至供应商都不同哈) 那个网络传输速度,快的飞起来。

 

这个是我写请求聚合的代码:

 

我这就请求了zuul一个服务,然后就全权交给zuul给我把我要的数据都拿到了,组合成一个数据响应给我,是不是非常nice。我客户端的请求代码编写,也变得简单了。

 

到现在为止,整个Zuul架构就差不多了。自定义过滤器、回退、请求聚合、我还提供了一个zuul的集群高可用方案。基本上可以满足大多生产需求。

我的项目地址:Github

阅读全文
EA PLAYER &

历史记录 [ 注意:部分数据仅限于当前浏览器 ]清空

      00:00/00:00