SpringCloud技术点介绍以及设计模式和SpringCloud netfix解决方案

    科技2022-07-20  111

    SpringCloud

    在众多的架构中,spring家族占据了主导的位置,同样对于spring衍生出的产品我们也应该去探索,今天我们将看下什么是微服务架构,以及微服务架构的解决方案,

    学习微服务架构必须有三年以上的开发的经验:

    微服务概念

    把一个大型的单体应用拆分为数十个支持微服务,他可扩展单个组件而不是整个的应用程序堆栈,从而满足服务等级协议

    ​ 定义:围绕业务领域组件进行创建组件,这些应用可独立进行开发,管理迭代,在分散的组件中使用云架构和平台式部署,管理,和服务功能,使得产品交互更加的简单

    ​ 本质:是用一些功能比较明确的,业务精练的服务去解决更大的更实际的问题,(2012年为微服务元年)

    微服务架构:

    微服务架构是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。 它的主要作用是将功能分解到离散的各个服务当中,从而降低系统的耦合性,并提供更加灵活的服务支持。

    缺点

    ​ 1.微服务的另一个挑战是分区数据库架构。更新多个业务实体的业务事务是相当普遍的。这些事务在单体应用中的实现显得微不足道,因为单体只存在一个单独的数据库。在基于微服务的应用程序中,您需要更新不同服务所用的数据库。

    ​ 通常不会选择分布式事务,不仅仅是因为 CAP 定理。他们根本不支持如今高度可扩展的 NoSQL 数据库和消息代理。

    ​ 2.部署复杂

    ​ 3.测试微服务应用程序也很复杂

    ​ 4.微服务架构模式的另一个主要挑战是实现了跨越多服务变更

    ​ 5.每个服务都有多个运行时实例。还有更多的移动部件需要配置、部署、扩展和监控

    ​ 构建复杂的微服务应用程序本质上是困难的。单体架构模式只适用于简单、轻量级的应用程序,如果您使用它来构建复杂应用,您最终会陷入痛苦的境地。

    ​ 微服务架构模式是复杂、持续发展应用的一个更好的选择。尽管它存在着缺点和实现挑战

    ​ 微服务的数据的库的设置:是反范式的设计模式:根据情况来设计不同的数据库

    优点

    1.第一,它解决了复杂问题。它把可能会变得庞大的单体应用程序分解成一套服务。虽然功能数量不变,但是应用程序已经被分解成可管理的块或者服务。

    2.这种架构使得每个服务都可以由一个团队独立专注开发。开发者可以自由选择任何符合服务 API 契约的技术。

    3.微服务架构模式可以实现每个微服务独立部署。开发人员根本不需要去协调部署本地变更到服务。这些变更一经测试即可立即部署

    4.微服务架构模式使得每个服务能够独立扩展。您可以仅部署满足每个服务的容量和可用性约束的实例数目。此外,您可以使用与服务资源要求最匹配的硬件。目标在于充分分解应用程序以方便应用的敏捷开发和部署,

    CAP定理:

    ​ 一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。

    ​ C:即更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致。

    ​ A:即服务一直可用,而且是正常响应时间

    ​ P:即分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务

    CAP权衡:

    ​ C 必须保证。网络发生故障宁可停止服务,这是保证 CA,舍弃 P。貌似这几年国内银行业发生了不下 10 起事故,但影响面不大,报到也不多,广大群众知道的少。

    ​ 还有一种是保证 CP,舍弃 A。例如网络故障是只读不写。孰优孰略,没有定论,只能根据场景定夺,适合的才是最好的

    BASE理论:

    ​ ebay架构师在 ACM 上发表文章提出 BASE 理论,BASE 理论是对 CAP 理论的延伸,核心思想是即使无法做到强一致性(Strong Consistency,CAP 的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性(Eventual Consitency)。

    服务间的通信

    同步调用:网络间只有字符串可以通过穿透防火墙

    ​ Rest:(对外)Http通信

    ​ Rest API

    ​ String json=/usr/list; ​ User usr=new User(); ​ usr.setId(json.getId)

    ​ 使用框架:springboot+Spring Cloud;

    ​ RPC:(对内) 远程过程调用

    ​ 调用也是对内部的,同样需要new出的,但是不是直接new User()的,而是new 的另一个框架:Dubbo

    ​ 问题:就会出现阻塞,出现单点故障,

    ​ RPC 也有自己的优点,传输协议更高效,安全更可控,

    ​ 特别在一个公司内部,如果有统一个的开发规范和统一的服务框架时,

    ​ 他的开发效率优势更明显些。就看各自的技术积累实际条件,自己的选择了

    异步消息调用:

    ​ 异步消息的方式在分布式系统中有特别广泛的应用,他既能减低调用服务之间的耦合,又能成为调用之间的缓冲,确保消息积压不会冲垮被调用方, 同时能保证调用方的服务体验,继续干自己该干的活,不至于被后台性能拖慢。不过需要付出的代价是一致性的减弱,需要接受数据 最终一致性; 还有就是后台服务一般要实现 幂等性,因为消息送出于性能的考虑一般会有重复(保证消息的被收到且仅收到一次对性能是很大的考验);最后就是必须引入一个独立的 Broker

    ​ Kafka

    ​ Notify

    ​ MessageQueue ​

    服务间是如何发现的呢:

    ​ 在微服务架构中,一般每一个服务都是有多个拷贝,来做负载均衡。一个服务随时可能下线,也可能应对临时访问压力增加新的服务节点。

    ​ 服务之间如何相互感知?服务如何管理?

    ​ 这就是服务发现的问题了。一般有两类做法,也各有优缺点。基本都是通过 Zookeeper 等类似技术做服务注册信息的分布式管理。

    ​ 当服务上线时,服务提供者将自己的服务信息注册到 ZK(或类似框架),并通过心跳维持长链接,实时更新链接信息。服务调用者通过 ZK 寻址,根据可定制算法,找到一个服务,还可以将服务信息缓存在本地以提高性能。当服务下线时,ZK 会发通知给服务客户端

    基于客户端的服务注册与发现

    ​ 优点是架构简单,扩展灵活,只对服务注册器依赖。缺点是客户端要维护所有调用服务的地址,有技术难度,一般大公司都有成熟的内部框架支持,比如 Dubbo。

    ​ 每次需要调用服务时需要在zookeeper中注册发现中查询,前提是每一个服务新建时需要在这个注册中心,进行ip注册和端口,服务名称。

    基于服务端的服务注册与发现:

    ​ 优点是简单,所有服务对于前台调用方透明,一般在小公司在云服务上部署的应用采用的比较多。

    ​ 主要有这几个框架: ​ Eureka: ​ Consul: ​ Zookeeper:

    ​ 如果服务挂了如何解决呢:

    ​ 重试机制:即当没响应时他会自己再次发送请求,

    ​ 限流:秒杀机制,直接在客户端中让百分之90的人不能直接访问到服务,而是直接提示出,

    ​ 熔断机制:在服务端进行流量的控制

    ​ 负载均衡: 降级(本地缓存)

    服务注册与发现原理:

    单点故障:

    ​ 在分不式锁服务中,有一种典型的应用场景,通过集群对Master进行选举, ​ 即主节点不能使用的话,既不能为从节点提供服务。 ​ 传统的解决方案:主节点-------》备用主节点 ​ 备用主节点------》》从节点 《《--------主节点 ​ 这种方式网络突然有问题时会进行对回复时就会丢失包,而这样的情况就是就会把两个主节点都是在这里 ​ 主要使用zookeeper来解决这个问题,服务注册与发现 ​ 引入:为什么使用分布式锁:

    微服务架构的设计模式:

    微服务架构需要考虑的问题:

    API Gateway服务间调用服务发现服务容错服务部署数据调用

    微服务设计模式:

    ​ 聚合器微服务形式::由api网关进行对其聚合

    ​ 代理微服务设计模式:代理委派请求,在这种情况下,客户端并不聚合数据,但会根据业务需求的差别调用不同的微服务。代理可以仅仅委派请求,也可以进行数据转换工作

    ​ 链式微服务设计模式:链式同步调用,这种模式在接收到请求后会产生一个经过合并的响应

    ​ 分支微服务设计模式:同时允许两个微服务链,这种模式是聚合器模式的扩展,允许同时调用两个微服务链

    ​ 数据共享微服务设计模式:SQL数据库反规范化可能会导致数据重复和不一致。自治是微服务的设计原则之一,就是说微服务是全栈式服务。但在重构现有的“单体应用(Monolithic Application)”时,SQL 数据库反规范化可能会导致数据重复和不一致。因此,在单体应用到微服务架构的过渡阶段,可以使用这种设计模式

    ​ 异步消息传递微服务设计模式:使用消息队列,虽然 REST 设计模式非常流行,但它是同步的,会造成阻塞。因此部分基于微服务的架构可能会选择使用消息队列代替 REST 请求/响应

    微服务架构开发建议:

    应用程序的核心是业务逻辑,按照业务或客户需求组织资源(这是最难的) 做有生命的产品,而不是项目 全栈化 后台服务贯彻 Single Responsibility Principle(单一职责原则) VM -> Docker DevOps springCloud 基于springboot的技术技术框架; java原生云开发=springCloud+spring boot

    分布式系统开发一定会遇到的四个问题以及解决方案:

    ​ 1.服务众多,客户端如何访问。

    ​ 2.服务众多,服务之间如何通信。

    ​ 3.服务众多,如何治理。

    ​ 4.服务众多,如果挂了怎么办;

    这四个问题对应了解决四个问题的方式:

    ​ 1.API网关,服务路由

    ​ 2.Http,RPC,异步调用

    ​ 3.服务注册与发现 -》高可用

    ​ 4.熔断,限流,服务降级

    解决方案:

    ​ SpringCloud,spring Cloud是一套生态,是为了解决微服务架构遇到的问题,想要使用Spring Cloud必须基于Spring Boot

    1.Spring Cloud Netflix

    ​ API网关,zuul组件

    ​ 服务注册与发现,Eureka

    ​ Fegin -> http Client -->http通信方式,同步阻塞

    熔断机制 Hystrix

    2.Apache Dubbo Zookeeper

    Dubbo是一个高效性能的 Java RPC 通信框架,2.6.x 服务注册与发现,Zookeeper, API网关 没有 找第三方或自己实现。 服务挂了,Hystrix

    3.Spring Cloud Alibaba

    Spring Cloud Alibaba致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。

    依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。

    下一代会是什么呢,Service Mesh 服务网格化,Istio 可能是需要掌握的一套微服务解决方案。

    SpringCloud Netflix:

    到2019目前最流行的微服务架构解决方案是:springBoot+spring cloud Netflix

    Spring Cloud 为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线)。分布式系统的协调导致了样板模式, 使用 Spring Cloud 开发人员可以快速地支持实现这些模式的服务和应用程序。他们将在任何分布式环境中运行良好,包括开发人员自己的笔记本电脑,裸机数据中心,以及 Cloud Foundry 等托管平台。

    ​ Spring Cloud 是基于Spring Boot进行开发,并且都是使用 Maven 做项目管理工具。 然而在2019年Spring Cloud Netflix 开始进入维护模式。所以使用的少了。

    下面看看如何使用Spring Cloud Netflix 搭建一个微服务架构

    创建一个依赖管理项目:

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.2.RELEASE</version> </parent> <groupId>com.funtl</groupId> <artifactId>hello-spring-cloud-dependencies</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>pom</packaging> <name>hello-spring-cloud-dependencies</name> <url>http://www.funtl.com</url> <inceptionYear>2018-Now</inceptionYear> <properties> <!-- Environment Settings --> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!-- Spring Settings --> <spring-cloud.version>Finchley.RC1</spring-cloud.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <!-- Compiler 插件, 设定 JDK 版本 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <showWarnings>true</showWarnings> </configuration> </plugin> <!-- 打包 jar 文件时,配置 manifest 文件,加入 lib 包的 jar 依赖 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <addMavenDescriptor>false</addMavenDescriptor> </archive> </configuration> <executions> <execution> <configuration> <archive> <manifest> <!-- Add directory entries --> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> <addClasspath>true</addClasspath> </manifest> </archive> </configuration> </execution> </executions> </plugin> <!-- resource --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> </plugin> <!-- install --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-install-plugin</artifactId> </plugin> <!-- clean --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-clean-plugin</artifactId> </plugin> <!-- ant --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> </plugin> <!-- dependency --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> </plugin> </plugins> <pluginManagement> <plugins> <!-- Java Document Generate --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <executions> <execution> <phase>prepare-package</phase> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <!-- YUI Compressor (CSS/JS压缩) --> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>yuicompressor-maven-plugin</artifactId> <version>1.5.1</version> <executions> <execution> <phase>prepare-package</phase> <goals> <goal>compress</goal> </goals> </execution> </executions> <configuration> <encoding>UTF-8</encoding> <jswarn>false</jswarn> <nosuffix>true</nosuffix> <linebreakpos>30000</linebreakpos> <force>true</force> <includes> <include>/*.js</include> <include>/.css</include> </includes> <excludes> <exclude>**/.min.js</exclude> <exclude>*/.min.css</exclude> </excludes> </configuration> </plugin> </plugins> </pluginManagement> <!-- 资源文件配置 --> <resources> <resource> <directory>src/main/java</directory> <excludes> <exclude>*/.java</exclude> </excludes> </resource> <resource> <directory>src/main/resources</directory> </resource> </resources> </build> <repositories> <repository> <id>aliyun-repos</id> <name>Aliyun Repository</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>sonatype-repos</id> <name>Sonatype Repository</name> <url>https://oss.sonatype.org/content/groups/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>sonatype-repos-s</id> <name>Sonatype Repository</name> <url>https://oss.sonatype.org/content/repositories/snapshots</url> <releases> <enabled>false</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>aliyun-repos</id> <name>Aliyun Repository</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> </project>

    创建服务注册与发现:

    用的是Eureak是一个服务注册和发现模块(与zookeeper的作用是一样的)引入配置文件pom.xml启动一个服务注册中心:需要注解@EnableEureakaServcer配置application.yml文件:每一个实例注册之后需要向注册中心发送心跳(因此可以在内存中完成),在默认情况下 Erureka Server 也是一个 Eureka Client ,必须要指定一个 Server。通过服务可以打开浏览器进行访问http://localhost:8761

    创建服务提供者:

    ​ 当 Client 向 Server 注册时,它会提供一些元数据,例如主机和端口,URL,主页等。Eureka Server 从每个 Client 实例接收心跳消息。 如果心跳超时,则通常将该实例从注册 Server 中删除

    引入pom.xm文件:

    application中的yml

    spring: application: name: hello-spring-cloud-service-admin server: port: 8762 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/

    创建服务消费者Ribbon:

    pom.xml: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.funtl</groupId> <artifactId>hello-spring-cloud-dependencies</artifactId> <version>1.0.0-SNAPSHOT</version> <relativePath>../hello-spring-cloud-dependencies/pom.xml</relativePath> </parent> <artifactId>hello-spring-cloud-web-admin-ribbon</artifactId> <packaging>jar</packaging> <name>hello-spring-cloud-web-admin-ribbon</name> <url>http://www.funtl.com</url> <inceptionYear>2018-Now</inceptionYear> <dependencies> <!-- Spring Boot Begin --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Spring Boot End --> <!-- Spring Cloud Begin --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <!-- Spring Cloud End --> <!-- 解决 thymeleaf 模板引擎一定要执行严格的 html5 格式校验问题 --> <dependency> <groupId>net.sourceforge.nekohtml</groupId> <artifactId>nekohtml</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.funtl.hello.spring.cloud.web.admin.ribbon.WebAdminRibbonApplication</mainClass> </configuration> </plugin> </plugins> </build> </project>
    在application.yml中书写配置文件:
    spring: application: name: hello-spring-cloud-service-admin server: port: 8762 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/

    ​ 创建服务feign:feign是集成了ribbon的一个服务消费者:项目中使用用Feign 可以理解为将ribbon峰会在哪个了一次

    熔断器防止服务雪崩:

    ​ 在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以通过 RPC 相互调用,在 Spring Cloud 中可以用 RestTemplate + Ribbon 和 Feign 来调用。为了保证其高可用,单个服务通常会集群部署。

    ​ 由于网络原因或者自身的原因,服务并不能保证 100% 可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet 容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的 “雪崩” 效应。

    1.在feign中使用:
    Feign中自带熔断器: feign: hystrix: enabled: true ===== service中指定fallback的类: @FeignClient(value = "hello-spring-cloud-service-admin", fallback = AdminServiceHystrix.class) public interface AdminService { @RequestMapping(value = "hi", method = RequestMethod.GET) public String sayHi(@RequestParam(value = "message") String message); } ==== 创建这个借口的实现类: @Component public class AdminServiceHystrix implements AdminService { @Override public String sayHi(String message) { return "Hi,your message is :"" + message + "" but request error."; } }
    2.在ribbon中使用:

    pom.xml中加入:

    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>

    ​ 主函数中加入注解@EnableHystrix ​在service中使用:

    @HystrixCommand(fallbackMethod = "hiError") public String sayHi(String message) { return restTemplate.getForObject("http://HELLO-SPRING-CLOUD-SERVICE-ADMIN/hi?message=" + message, String.class); } public String hiError(String message) { return "Hi,your message is :"" + message + "" but request error."; }
    使用熔断仪器监控hystrix:

    pom.xml中加入:

    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency> @Configuration public class HystrixDashboardConfiguration { @Bean public ServletRegistrationBean getServlet() { HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet(); ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet); registrationBean.setLoadOnStartup(1); registrationBean.addUrlMappings("/hystrix.stream"); registrationBean.setName("HystrixMetricsStreamServlet"); return registrationBean; } }

    ​ 测试熔断localhost:8764/hystrix

    hystrix触发fallback的方法:、

    ​ timeout,SHORT_CIRCUITED:断路器打开不尝试执行,THREAD_POOL_REJECTED:线程池拒绝,不尝试执行,SEMAPHORE_REJECTED 信号量拒绝,不尝试执行 YES

    使用统一的网关访问接口zuul:

    ​ 在 Spring Cloud 微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(Zuul、Ngnix),再到达服务网关(Zuul 集群),然后再到具体的服。 服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理,配置服务的配置文件放在 GIT 仓库,方便开发人员随时改配置

    zuul:

    ​ Zuul 的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如 /api/user 转发到到 User 服务,/api/shop 转发到到 Shop 服务。Zuul 默认和 Ribbon 结合实现了负载均衡的功能。

    pom.xml中加入:
    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency>
    application.yml中书写配置文件:
    spring: application: name: hello-spring-cloud-zuul server: port: 8769 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ ##以/api/a/请求全部转发到ribbon服务中,以/api/b/全部转发到feign服务## zuul: routes: api-a: path: /api/a/** serviceId: hello-spring-cloud-web-admin-ribbon api-b: path: /api/b/** serviceId: hello-spring-cloud-web-admin-feign

    ​ 创建回调的类:主要是创建对对其出现错误后的回调机制:

    主函数:
    @SpringBootApplication @EnableEurekaClient @EnableZuulProxy public class ZuulApplication { public static void main(String[] args) { SpringApplication.run(ZuulApplication.class, args); } }

    ​ 其实就是聚合其他的服务:以上聚合了ribbon和feign两个服务。 ​

    分布式配置中心:

    ​ 有分布式配置中心组件 Spring Cloud Config ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程 Git 仓库中。在 Spring Cloud Config 组件中,分两个角色,一是 Config Server,二是 Config Client。

    分布式配置中心服务端:
    pom.xml中加入:
    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.funtl</groupId> <artifactId>hello-spring-cloud-dependencies</artifactId> <version>1.0.0-SNAPSHOT</version> <relativePath>../hello-spring-cloud-dependencies/pom.xml</relativePath> </parent> <artifactId>hello-spring-cloud-config</artifactId> <packaging>jar</packaging> <name>hello-spring-cloud-config</name> <url>http://www.funtl.com</url> <inceptionYear>2018-Now</inceptionYear> <dependencies> <!-- Spring Boot Begin --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Spring Boot End --> <!-- Spring Cloud Begin --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <!-- Spring Cloud End --> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.funtl.hello.spring.cloud.config.ConfigApplication</mainClass> </configuration> </plugin> </plugins> </build> </project>

    在ConfigApplication中开启:

    @SpringBootApplication @EnableConfigServer @EnableEurekaClient public class ConfigApplication { public static void main(String[] args) { SpringApplication.run(ConfigApplication.class, args); } }
    在application.yml中书写配置文件:
    spring: application: name: hello-spring-cloud-config cloud: config: label: master server: git: uri: https://github.com/topsale/spring-cloud-config search-paths: respo username: password: server: port: 8888 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
    配置说明:

    ​ spring.cloud.config.label:配置仓库的分支

    ​ spring.cloud.config.server.git.uri:配置 Git 仓库地址(GitHub、GitLab、码云 ...)​

    ​ spring.cloud.config.server.git.search-paths:配置仓库路径(存放配置文件的目录)

    ​ spring.cloud.config.server.git.username:访问 Git 仓库的账号

    ​ spring.cloud.config.server.git.password:访问 Git 仓库的密码

    分布式配置中心客户端配置:
    pom.xml中配置:
    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.funtl</groupId> <artifactId>hello-spring-cloud-dependencies</artifactId> <version>1.0.0-SNAPSHOT</version> <relativePath>../hello-spring-cloud-dependencies/pom.xml</relativePath> </parent> <artifactId>hello-spring-cloud-config-client</artifactId> <packaging>jar</packaging> <name>hello-spring-cloud-config-client</name> <url>http://www.funtl.com</url> <inceptionYear>2018-Now</inceptionYear> <dependencies> <!-- Spring Boot Begin --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Spring Boot End --> <!-- Spring Cloud Begin --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <!-- Spring Cloud End --> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.funtl.hello.spring.cloud.config.client.ConfigClientApplication</mainClass> </configuration> </plugin> </plugins> </build> </project>

    入口类处理方式: ​

    @SpringBootApplication @EnableDiscoveryClient public class ConfigClientApplication { public static void main(String[] args) { SpringApplication.run(ConfigClientApplication.class, args); } }
    application.yml中书写配置文件:
    spring: application: name: hello-spring-cloud-config-client cloud: config: uri: http://localhost:8888 name: config-client label: master profile: dev server: port: 8889 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
    配置说明:

    spring.cloud.config.uri:配置服务中心的网址 ​ spring.cloud.config.name:配置文件名称的前缀 ​ spring.cloud.config.label:配置仓库的分支 ​ spring.cloud.config.profile:配置文件的环境标识 ​ dev:表示开发环境 ​ test:表示测试环境 ​ prod:表示生产环境

    服务链路追踪:

    这里主要使用ZipKin: 每个服务向 ZipKin 报告计时数据,ZipKin 会根据调用关系通过 ZipKin UI 生成依赖关系图,显示了多少跟踪请求通过每个服务,该系统让开发者可通过一个 Web 前端轻松的收集和分析数据,例如用户每次请求服务的处理时间等,可方便的监测系统中存在的瓶颈 。

    ​ 说明:

    ​ 微服务架构是通过业务来划分服务的,使用 REST 调用。对外暴露的一个接口,可能需要很多个服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败。随着业务的不断扩张,服务之间互相调用会越来越复杂。

    服务监控:

    ​ admin ​ 启动顺序: ​ config->eureka—>--->zipkin—>Admin—>serviceAdmin—>ZuulApplication

    这就是简单的搭建,我们已经会用了,但是我们对各个组件还不是很深入,下面我们将会继续深入到各个组件,

    Processed: 0.012, SQL: 8