小工具      在线工具  汉语词典  css  js  c++  java

什么是微服务

单体应用

与微服务相反的另一个概念是传统的单体应用程序,它包含所有必需的服务。而且各个服务功能模块耦合性强,即相互依赖,难以拆分和扩展。

单体应用的优点:

  • 开发简单,功能全部在一个程序内,方便软件设计和开发规划。
  • 易于部署,程序单一,没有分布式集群的复杂部署环境,降低了部署难度。
  • 易于测试,没有复杂的服务调用关系,都是内部调用,方便测试。

当然,也存在一些缺点。单体应用服务之间具有较高的紧密度和依赖性,这会导致测试和升级困难,并且后期开发曲线可能会大幅增加,导致开发困难。相比之下,“微服务架构”可以解决这个问题。

微服务

它在维基百科上的定义是:一种软件开发技术——面向服务架构(SOA)架构风格的一种变体,它主张将单个应用程序划分为一组小的服务,服务之间相互协调配合。 ,为用户提供最终价值。每个服务都运行在自己独立的进程中,服务之间使用轻量级通信机制(通常是基于HTTP的RESTful API)进行通信。每个服务都是围绕特定业务构建的,可以独立部署到生产环境、类生产环境等。

微服务的优点:

  1. 技术异构性意味着不同服务内部的开发技术可能不一致。可以使用Java开发服务A,使用golang开发服务B。不同的服务使用不同的技术栈。
  2. 隔离性,一个服务的不可用不会导致另一个服务的失败,因为每个服务都是一个独立自治的系统。这在整体应用程序中是不可能的。
  3. 可扩展性:如果一个庞大的单一服务遇到性能瓶颈,整个软件就只能进行扩展。在微服务架构中,只有影响性能的服务才能进行扩展和升级。
  4. 简化部署。在微服务架构中,每个服务的部署都是独立的。

总之,微服务架构是一种将单个应用程序开发为一组小型服务的方法,每个服务都在自己的进程中运行并使用轻量级机制进行通信,这些服务是围绕业务功能构建的,可以完全自动化和独立部署。这些服务是最低限度集中管理的,可以用不同的编程语言编写,并使用不同的数据存储技术。

微服务与分布式有什么区别

微服务是基于分而治之的思想演化而来的。过去是传统的大型综合体系。随着互联网的发展,已经很难满足市场对技术的需求。所以我们从单机架构发展到分布式架构,又从分布式架构发展到SOA架构,服务持续化。它被拆分、分解,粒度越来越小,直到微服务架构的诞生。微服务架构是一种主张将单个应用程序划分为一组小型服务的架构模式。各项服务相互协调配合,为用户提供最终价值。微服务架构和分布式架构的区别在于部署方式。分布式就是将一个大系统划分为多个业务模块。这些业务模块将部署在不同的机器上,通过接口与数据进行交互。微服务应用程序可以部署在同一台服务器上,不一定分布在多台服务器上。

微服务是真正分布式和去中心化的。将包括路由、消息解析等在内的所有“思考”逻辑都放在服务内部,去掉统一的ESB,服务之间轻通信,是比SOA更彻底的拆分。

微服务架构的重点是业务系统需要完全组件化、服务化。将原来单一的业务系统拆分成多个可以独立开发、设计、运行和维护的小应用。这些小应用通过服务连接起来完成交互和集成。

微服务解决系统复杂性问题,分布式解决系统性能问题。两者的概念层面也不同:微服务处于设计层面,一般考虑如何对系统进行逻辑拆分,即垂直拆分;而分布是在部署层面,强调的是物理层面的组成。 ,即系统的各个子系统部署在不同的计算机上。微服务可以是分布式的,即不同的服务可以部署在不同的计算机上。当然,如果体积较小,也可以部署在单机上。

SOA(Service Oriented Architecture):是一种包含多种服务的设计方法,服务之间通过相互依赖最终提供一系列的功能。服务通常以独立的形式存在于操作系统进程中。每个服务都是通过网络调用的。

ESB和微服务API网关:
ESB(企业服务总线), 就是一根管道,用来连接各个服务节点。为了集 成不同系统,不同协议的服务,ESB 做了消息的转化解释和路由工作,让不同的服务互联互通;

API网关:API网关是服务器,是系统的唯一入口。从面向对象设计的角度来看,它类似于门面模式。 API网关封装了系统内部架构,为每个客户端提供定制化的API。它还可能具有其他职责,例如身份验证、监控、负载平衡、缓存、请求分片和管理以及静态响应处理。 API网关方式的核心点是所有客户端和消费者都通过统一网关访问微服务,所有非业务功能都在网关层处理。通常,网关还提供REST/HTTP访问API。服务器通过API-GW注册和管理服务。

在这里插入图片描述
Dubbo服务架构是SOA的最佳实践。

微服务架构

在这里插入图片描述

微服务架构是一种在云中部署应用程序和服务的新技术。围绕微服务的大部分争论都集中在容器或其他技术是否擅长实现微服务。

微服务可以“在自己的程序中”运行,并通过“具有基于 HTTP 的 API 的轻量级设备”进行通信。关键是服务可以运行在自己的程序中。通过这一点,我们可以将服务暴露与微服务架构(在现有系统中分发API)区分开来。在服务暴露中,很多服务可以被限制在内部独立的进程中。如果这些服务中的任何一个需要附加功能,则必须缩小流程范围。在微服务架构中,您只需要为特定的服务添加所需的功能,而不影响整体流程架构。

从概念上理解,分布式服务架构强调服务的服务化、去中心化,而微服务则强调服务专业化、精细化分工。从实践的角度来看,微服务架构通常是分布式服务架构,反之亦然。可能不成立。因此,选择微服务通常意味着解决分布式架构的各种问题。

区分分布的方式是不同的服务基于不同的机器。

将一个大系统划分为多个业务模块,将业务模块部署到不同的机器上,并通过接口进行交互。区分分布的方式是不同的服务基于不同的机器。

微服务更加强调单一职责、轻量级通信(HTTP)、独立性和进程隔离。

微服务与分布式的微妙区别在于,微服务的应用不一定分散在多台服务器上,也可以是同一台服务器。

传统开发模式:

在这里插入图片描述
微服务模式:
在这里插入图片描述

客户端如何访问这些服务:
Monolithic方式开发,所有的服务都是本地的,UI可以直接调用,现在按功能拆分成独立的服务,跑在独立的一般都在独立的虚拟机上的 Java进程了。客户端UI如何访问呢?

后台有N个服务,前台需要记住管理N个服务。如果某个服务下线/更新/升级,则前台必须重新部署。这显然不符合我们分流的理念,尤其是当前台是移动应用时。业务通常变化得更快。

另外,N个小服务的调用也是一笔不小的网络开销。系统内部还有通用的微服务,通常是无状态的。最好有一个统一的本地维护管理(OAuth)来进行用户登录信息和权限管理。

所以后台的N个服务和UI之间一般都会有一个代理或者API Gateway。其功能包括:

① 提供统一的服务入口,让微服务对前台透明

② 聚合后台服务,节省流量,提高性能

③ 提供安全、过滤、流量控制等API管理功能。

事实上,这个 API 网关可以通过多种方式实现。它可以是一个软硬件集成的盒子,也可以是一个简单的MVC框架,甚至可以是一个Node.js服务器。他们最重要的作用是为前台提供支持(通常是

移动应用)提供后台服务的聚合,提供统一的服务出口,并解耦。然而,API网关也可能成为单点故障或性能瓶颈。

所有微服务都是运行在独立虚拟机上的独立Java进程,因此服务之间的通信是IPC(进程间通信),并且已经有很多成熟的解决方案。目前最常用的方法有两种:

同步调用:

①REST(JAX-RS、Spring Boot)

②RPC(Thrift、Dubbo)

异步消息调用(Kafka、Notify、MetaQ)

在这里插入图片描述

微服务架构是使用一套小服务来开发单个应用的方式或途径,每个服务基于单一业务能力构建,运行在自己的进程中,并使用轻量级机制通信,通常是HTTP API,并能够通过自动化部署机制来独立部署。这些服务可以使用不同的编程语言实现,以及不同数据存储技术,并保持最低限度的集中式管理。

微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个微服务提供单个业务功能的服务,一个服务做一件事,从技术角度看就是一种小而独立的处理过程,类似进程概念,能够自行单独启动或销毁,拥有自己独立的数据库。

参考文档

1、服务集群
  单体项目拆分成独立项目(服务,每个服务完成一部分的业务功能)形成服务集群。一个业务往往需要多个服务去完成。

2、注册中心
  大量且复杂的业务会使服务之间的调用关系非常复杂,人工无法完成,注册中心就是用于记录每个服务的IP、端口及作用这些信息,当一个服务需要调用其他服务时,只需要从注册中心拉取对应的服务信息即可,无需自己记录。

注册中心的功能可以用一句话概括就是存储和调度服务,实现服务与注册中心、服务之间的相互通信。注册中心可以说是微服务架构中的“通讯录”。它记录了服务和服务地址之间的映射关系。在分布式架构中,服务将在这里注册。当服务需要调用其他服务时,就会找到这里服务的地址并调用。

常用的注册中心中间件

特征 尤里卡 纳科斯 领事 动物园管理员
访问协议 HTTP协议 HTTP/DNS HTTP/DNS 传输控制协议
监控支持 支持· 支持· 支持· 支持·
多个数据中心 支持· 支持· 支持· 不支持·
春云 支持· 支持· 支持· 支持·
健康检查 客户节拍 TCP/HTTP/MYSQL/客户端节拍 TCP/HTTP/CMD 保持一切活力

3、配置中心
  服务越来越多,每个服务都会有很多配置信息,配置中心可以做到统一管理集群中的所有配置。若有配置变更,找到配置中心,它会通知相关的服务实现配置的“热更新”。

在微服务架构中,当系统从一个单体应用,被拆分成分布式系统上一个个服务节点后,配置文件也必须跟着分割,这样配置就分散了,再考虑到多环境配置文件参数不同的情况。所以这时候我们就需要配置中心。
配置中心的作用就是将配置从各应用中剥离出来,对配置进行统一管理,应用自身不需要自己去管理配置。

常见的配置中心有Nacos、Apollo、Disconf。

4、服务网关
  一方面对用户身份做校验,将用户请求路由到具体的微服务,也可以做一些负债均衡。网关是微服务架构中的一个关键的角色,用来保护、增强和控制对于微服务的访问。网关是一个处于应用程序或服务之前的系统,用来管理授权、访问控制和流量限制等,这样微服务就会被微服务网关保护起来,对所有的调用者透明。因此,隐藏在微服务网关后面的业务系统就可以更加专注于业务本身。同时,微服务网关还可以为服务提供和沉淀更多附加功能。

在这里插入图片描述

5、数据库
  数据库也可能是集群,但仍可能无法抗住并发,需要引入缓存。主要职责就是做一些写操作或者事务类型的对数据安全要求较高的数据存储。

6、分布式缓存
  缓存就是将数据存在内存中,数据库则是存在磁盘上,优劣可见。应对高并发需要将缓存做成分布式缓存。用户请求先到缓存,缓存未命中再访问数据库。
  
7、分布式搜索
  海量数据的搜索,统计和分析可以用分布式搜索完成,简单的查询可以走缓存。
  
8、消息队列
  正常情况一个业务可能需要走多个服务,A-B-C-D,由A调用B,B调用C,C调用D,时间就是这几个服务调用的时间之和,往往实际业务可能更复杂,这样长链路调用会对性能造成影响,于是引进了消息队列。调用A后,A发一个消息给BCD,让BCD开始工作,A则是结束就直接关掉了,链路变短以及吞吐能力加强,做到异步通信的效果,从而提高效率。

常见的消息队列有:RabbitMQ、RocketMQ、ActiveMQ、Kafka等。

10、分布式日志服务
  庞大复杂的系统不易排查定位问题,需引入分布式日志服务,方便分体追踪排查。
  
9、系统监控链路追踪
  实时监控集群中每个服务节点的运行状态,cup负载以及内存的占用等等情况,一旦出现任何问题可以直接定位到异常信息。

在这里插入图片描述

SpringCloud和Dubbo的区别

微服务架构有六种类型: 1. Dubbo; 2.莫坦; 3. 焦油; 4. 春云; 5.gRPC; 6.节俭。 Dubbo是一个分布式服务框架,致力于提供高性能、透明的RPC远程服务调用解决方案和SOA服务治理解决方案。

Spring Boot专注于快速、便捷地开发单个微服务。 Spring Cloud是一个专注于全局微服务的协调和管理的框架,集成和管理Spring Boot开发的各个微服务。

参考文档感谢作者!

春云中文网站

Spring Cloud子项目包括:

  • Spring Cloud Config:配置管理开发工具包,允许您将配置放在远程服务器上。目前它支持本地存储、Git 和 Subversion。

  • Spring Cloud Bus:事件和消息总线,用于传播集群中的状态变化(例如配置更改事件),可以与Spring Cloud Config结合实现热部署。

  • Spring Cloud Netflix:多种Netflix组件的开发工具包,包括Eureka、Hystrix、Zuul、Archaius等。

  • Netflix Eureka:Cloud Load Balancing,一种基于REST的服务,用于定位服务以实现云中的负载均衡和中间层服务器的故障转移。

  • Netflix Hystrix:一种容错管理工具,旨在通过控制服务和第三方库的节点来为延迟和故障提供更大的容错能力。

  • Netflix Zuul:边缘服务工具,这是一种边缘服务,提供动态路由、监控、弹性、安全性等。

  • Netflix Archaius:配置管理API,包括一系列配置管理API,提供动态类型化属性、线程安全的配置操作、轮询框架、回调机制等功能。

  • Spring Cloud for Cloud Foundry:通过Oauth2协议将服务绑定到CloudFoundry。 CloudFoundry是VMware推出的开源PaaS云平台。

  • Spring Cloud Sleuth:日志收集工具包,封装了Dapper、Zipkin和HTrace操作。

  • Spring Cloud Data Flow:一个大数据操作工具,通过命令行操作数据流。

  • Spring Cloud Security:向应用程序添加安全控制的安全工具包,主要是 OAuth2。

  • Spring Cloud Consul:封装Consul操作。 Consul是一个服务发现和配置工具,可以与Docker容器无缝集成。

  • Spring Cloud Zookeeper:操作Zookeeper的工具包,用于使用zookeeper进行服务注册和发现。

  • Spring Cloud Stream:数据流操作开发包,封装了与Redis、Rabbit、Kafka等发送和接收消息。

  • Spring Cloud CLI:基于Spring Boot CLI,它允许您通过命令行快速构建云组件。

Dubbo是一个高性能、轻量级的开源Java RPC框架,提供了三大核心能力:面向接口的远程方法调用、智能容错和负载均衡、自动服务注册和发现。

在这里插入图片描述
详细介绍

1.Registry:服务注册和发现中心,作为服务提供者和消费者的注册和发现中心。

2、服务提供者:服务提供者在注册中心注册为服务提供者,并向服务注册中心发布服务。

3. 消费者:服务消费者,通过注册中心协调,订阅可用的注册服务。

4.容器:服务运行容器。独立容器类似于tomcat/jboss,作为服务运行的容器。

5、监控:Dubbo的监控中心用于显示接口暴露和注册状态。还可以查看接口调用详情、调用时间等。

在这里插入图片描述

1、由于dubbo是二进制传输,所以占用带宽较少。

2、SpringCloud采用http协议传输,会有更多的带宽。使用http协议时,一般会使用JSON消息,消耗较多。

3、dubbo的开发比较困难,因为很多大型项目无法解决dubbo的jar包的依赖问题。

4、Springcloud的接口协议相对自由和宽松,需要强有力的管理措施来限制无序的接口升级。

5、Dubbo的注册中心可以选择zk、redis等,springcloud的注册中心使用eureka或者Consul。

微服务实践

1. 客户如何获得这些服务?

传统的开发方式,所有服务都是本地的,UI可以直接调用。现在它们按照功能拆分成独立的服务,并运行在独立的Java进程中,通常是在独立的虚拟机上。客户端 UI 如何访问它?后端有N个服务,前端需要记住管理N个服务。如果服务离线/更新/升级,则必须重新部署前端。这显然不符合我们拆分的理念,尤其是当前端是移动应用时。业务通常变化得更快。另外,N个小服务的调用也是一笔不小的网络开销。系统内部还有通用的微服务,通常是无状态的。最好有一个统一的本地维护管理(OAuth)来进行用户登录信息和权限管理。所以后台的N个服务和UI之间一般都会有一个代理或者API Gateway。其功能包括提供统一的服务入口、让微服务对前台透明、聚合后台服务、节省流量、提高性能、提供安全等。 、过滤、流量控制等API管理功能。

2、服务之间如何通信?

由于所有微服务都是运行在独立虚拟机上的独立Java进程,服务之间的通信是IPC(进程间通信),并且有很多成熟的解决方案。现在最常见的有:HTTP(JAX-RS、Spring Boot)、RPC(Thrift、Dubbo)、异步消息调用(Kafka、Notify)

在这里插入图片描述

3. 这么多服务怎么找到?

在微服务架构中,每个服务一般都有多个副本,用于负载均衡。服务随时可能下线,或者增加新的服务节点来应对临时的访问压力。服务如何相互了解?服务如何管理?这就是服务发现的问题。通常有两种类型的方法,每种方法都有自己的优点和缺点。基本上,服务注册信息的分布式管理是通过zookeeper等类似技术来完成的。当服务上线时,服务提供者向Zookeeper(或类似框架)注册自己的服务信息,通过心跳维护长链接,并实时更新链接信息。服务调用者使用 ZooKeeper 寻址来根据可定制的算法查找服务。服务信息也可以缓存在本地以提高性能。当服务离线时,Zookeeper会向服务客户端发送通知。

4. 如果服务宕机了怎么办?

分发最大的特点就是对网络的依赖。如果遇到某个服务,可能会影响其所在应用程序的性能,从而影响所有调用该应用程序服务的前台应用程序。因此,当系统由一系列的服务调用链组成时,我们必须保证任何一个环节出现问题都不会影响整体环节。相应的技术包括:

  • 重试机制

常见的重试模式主要有两种:就地重试和异步重试。原位重试很容易理解,就是程序调用下游服务失败时重新发起;异步重试就是将请求信息扔到某个MQ中,然后程序会消费这个事件并重试。

  • 限制

依赖服务的业务请求被阻止,用户将不会收到响应。服务器支持的线程数和并发数是有限的,请求总是被阻塞,这会导致服务器资源耗尽,导致其他所有服务不可用。

限流的目的是通过限制并发访问/请求的速率或限制某个时间窗口内的请求速率来保护系统。一旦达到速率限制,服务可以被拒绝(定向到错误页面或通知资源消失)、排队或等待(如闪购、评论、订单)、降级(返回自下而上的数据或默认数据,例如产品详细信息页面库存默认可用性)。

目前开发高并发系统常见的限制包括:限制总并发数(如数据库连接池、线程池)、限制瞬时并发数(如nginx的limit_conn模块,用于限制瞬时并发数)并发连接数),并限制时间窗口内的瞬时并发连接数。平均速率(如Guava的RateLimiter和nginx的limit_req模块,限制每秒的平均速率);其他包括限制远程接口调用速率和限制MQ消耗速率。此外,还可以根据网络连接数、网络流量、CPU或内存负载等来限制电流。

  • 断路器

断路器机制是为了保护系统。例如,如果受到一些恶意攻击,就需要熔断机制来保护系统的微服务并做出响应,避免资源耗尽。它必须既具有响应性又具有保护性。当我们的请求达到负载阈值时,我们启用断路器,关闭真实接口,并向客户端请求响应。我们可以设置这个响应。服务断路器是对服务的调用执行断​​路器。对于后续的请求,目标服务不会继续被调用,而是直接返回,这样可以快速释放资源。如果服务失败,则会将故障信息返回给客户端。

断路器的功能:异常处理、日志记录、失败的测试操作、手动重置、并发、加速熔断、重试失败的请求

熔断和降级的区别:触发条件不同。熔断一般是故障引起的,降级一般是整体性能引起的。管理目标有不同层次。

  • 负载均衡

  • 降级(本地缓存)

为保证核心服务正常运行,部分服务、界面、页面将进行降级。降级处理一般是人工干预,可以配置。降级并断路器框架 Hystrix。

DevOps

庞大的系统手动部署不合实际,需进行持续集成。
1、Jenkins
  自动化编译

2、docker
  打包镜像

3、kubernetes/RANCHER
  实现自动化部署

Spring Cloud技术栈

技术栈介绍

spring cloud只是微服务的一种流行的技术体系,也还有其他Dubbo的技术

在这里插入图片描述
spring cloud netflix组件

在这里插入图片描述

spring cloud abibaba组件
在这里插入图片描述
spring cloud原生及其它组件
在这里插入图片描述

在这里插入图片描述

  • Spring云网关

SpringCloud Gateway基于WebFlux框架实现,WebFlux框架底层采用高性能Reactor模式通信框架Netty。其目标不仅是提供统一的路由方式,还提供基于Filter链的基础网关功能,并支持安全、监控/指标、限流等功能。

  • Spring云配置

Spring Cloud Config 为分布式系统中的外部配置提供服务器和客户端支持。方便部署和运维,分为客户端和服务端。服务器也称为分布式配置中心,是一个独立的微服务应用,用于连接配置服务器,为客户端提供访问接口,获取配置信息、加解密信息等。客户端管理应用资源和业务通过指定配置中心来获取相关配置内容,并在启动时从配置中心获取并加载配置信息。默认使用Git,通过git客户端工具可以轻松管理和访问配置内容。

  • Spring云总线

Spring Cloud Bus 将分布式系统的节点与轻量级消息代理连接起来。这可用于广播状态变化或其他管理指令。总线就像扩展的 Spring Boot 应用程序的分布式执行器,但也可以用作应用程序之间的通信通道。

  • 尤里卡

Spring Cloud Eureka是对Netflix的Eureka的二次封装。它实现了服务管理的功能。 Spring Cloud Eureka提供服务器和客户端。服务器是Eureka服务注册中心。客户端完成微服务来服务Eureka。注册并发现。

  • 海斯特里克斯

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

  • 费金

Fegin 是一个声明式 HTTP 客户端,这使得编写 HTTP 客户端变得更加容易。使用Fegin只需要创建一个接口并对其进行注释即可。它具有可插入的注释功能。 Nacos 与 Fegin 非常兼容,并且默认实现。为了达到负载均衡的效果,底层使用HttpClient作为服务框架。

  • 丝带

Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,基于Netflix Ribbon实现。通过Spring Cloud的封装,我们可以轻松地将面向服务的REST模板请求自动转换为客户端负载均衡的服务调用。虽然 Spring Cloud Ribbon 只是一个工具框架,并不需要像服务注册中心、配置中心、API 网关那样独立部署,但它几乎存在于 Spring Cloud 构建的每一个微服务和基础设施中。因为微服务之间的调用、API网关请求转发等其实都是通过Ribbon来实现的,包括后面我们要介绍的Feign,也是一个基于Ribbon实现的工具。因此,Spring Cloud Ribbon的理解和使用对于我们使用Spring Cloud构建微服务来说非常重要。

  • Sleuth
    Spring Cloud Sleuth为Spring Cloud实现了分布式跟踪解决方案。

  • 春云流

Spring Cloud Stream 是一个为微服务应用程序构建消息驱动功能的框架。它可以基于 Spring Boot 创建独立的、可用于生产的 Spring 应用程序。 Spring Cloud Stream为一些厂商的消息中间件产品提供了个性化的自动化配置实现,并引入了发布订阅、消费者组、分区三个核心概念。通过使用Spring Cloud Stream,开发者可以有效简化使用消息中间件的复杂度,让系统开发者更加专注于核心业务逻辑的处理。但目前Spring Cloud Stream仅支持RabbitMQ和Kafka的自动化配置。

案例搭建

  • 注册中心Eureka
    Eureka是Netflix开发的服务框架,SpringCloud将它集成到自己的子项目spring cloud netflix中,实现spring cloud的服务发现功能。
    在这里插入图片描述
    Eureka主要由三个角色组成:
  1. Eureka Server 提供注册和发现
  2. Servce Provider 服务提供者将自己的服务注册到Eureka,以便服务消费者可以找到它们。
  3. Servce Consumer 服务消费者从Eureka获取注册的服务列表,以便可以消费服务。

建立登记中心

  1. 搭建Eureka服务器
  • 创建项目

在这里插入图片描述

在构建的项目中每个模块就是一个独立的服务,例如product_service应为一个独立的spring boot程序,可以单独启动的服务:

在这里插入图片描述
在这里插入图片描述

同理order_service也是:
在这里插入图片描述

在这里插入图片描述

**创建工程并时独立的模块都能单独运行。但是微服务之间时存在互相调用的,不可能都借助浏览器进行,因此调用发生在硬代码之间,基于HTTP协议的调用通过RestTemplate对象调用。

在这里插入图片描述
该模板主要有以下几个方法:

在这里插入图片描述

创建过程:

在启动程序注入IoC容器即可。
在这里插入图片描述

在这里插入图片描述

...

@RestController
@RequestMapping(value = "/order")
public class OderController {
    

    @Autowired
    private UserService userService;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/roles")
    public List<User> method1(){
    
        List<User> users = userService.selectColumn();
        return users;
    }

    @GetMapping(value = "/order_role")
    public List<Role> method2(){
    
        List<Role> roles =restTemplate.getForObject("http://localhost:8080/role",List.class);
        return roles;
    }

}

在启动类注入了RestTemplate,调用类中主动装配,调用方法的第一个参数时url,第二个参数是对象类型,它的返回值类型和第二个参数是一致的,用法和JdbcTemplate类似。

访问对应路径并调用成功:

在这里插入图片描述

通过RestTemplate对象返回的是List<Role>泛型类型,所以还要为order_service创建Role对象,显然这不符合已服务为核心。这是模拟微服务的调用过程,后续的创建注册中心部分才正式进入微服务。

但仍然存在很多问题。现在每个服务的地址都是硬编码的。如果你想添加一个服务,你需要重写代码,删除它也是一样。这不符合微服务的特点。因此,需要服务发现、配置中心、消息总线、负载均衡、断路器、数据监控等技术来完成微服务的开发。

注册中心建设

  • 导入依赖项

构建注册中心模块,并在注册中心的配置模块中导入eureka依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    <version>...</version>
</dependency>
  • 配置文件
#配置eureka server

server.port=9000

# eureka的地址
eureka.instance.hostname=localhost

#是否将eureka注册到注册中心
eureka.client.register-with-eureka=false

#是否从eureka中获取注册地址
eureka.client.fetch-registry=false

eureka.client.service-url.defaultZone=http://localhost:9000/eureka/
  • 配置启动类

通过注解其启动注册中心模块
在这里插入图片描述

启动注册中心模块:

报错:Error creating bean with name 'configurationPropertiesBeans' defined in class path resource [org/springframework/cloud/autoconfigure/ConfigurationPropertiesRebinderAutoConfiguration.class]: Bean instantiation via factory method failed;

Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata

报错原因是:问题在spring-cloud-starter-netflix-eureka-client版本和SpringBoot版本不兼容,版本的搭配了具体我也不太清楚,就试出了一组可以正常启动的版本:

春季启动版本:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.9</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

尤里卡版本:

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>3.1.0</version>
        </dependency>

正常启动:
在这里插入图片描述

输入:http://localhost:9000/

在这里插入图片描述

  1. 向注册中心注册服务商

在创建的项目中,eureka模块相当于一个注册中心和一个服务器。其他模块都是客户端,所以需要在service模块中导入eureka-client:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    <version>3.1.0</version>
</dependency>

要关联客户端和服务器,请将以下内容添加到服务配置文件中:


eureka.client.service-url.defaultZone=http://localhost:9000/eureka/

# 使用ip地址注册
eureka.instance.prefer-ip-address=true

注解激活eureka-client,在启动类添加@EnableEurekaClient@EnableDiscoveryClient注解。

@SpringBootApplication
@MapperScan("com.example.product.dao")
@EnableEurekaClient
public class ProductApplication {
    

    public static void main(String[] args) {
    
        SpringApplication.run(ProductApplication.class, args);
    }

}

服务配置成功后,启动注册中心,进入后台管理查看服务:

在这里插入图片描述
只启动注册中心是没有服务的,再启动刚配置好的服务:

注意所有模块的spring boot的版本要保持一致,如果熟悉Maven的集成与融合可以通过继承来优化资源。

当一个服务启动后,就变成这样:

在这里插入图片描述
有一个服务但不知道名字,所以还需要配置,再服务模块的配置文件中追加:

# 配置服务的名称
spring.application.name=product_service

在这里插入图片描述
现在已将服务注册到注册中心了,并不是通过硬编码(像之前那样通过RestTemplate对象获取信息),而是将服务注册到注册中心由其自己管理。

通过eureka-server可以获取Eureka中的主机名、IP信息服务名、IP等元数据,用于服务之间的相互调用。

  1. 服务消费者通过注册中心获取服务列表并调用相关服务

eureka-server的服务调用通过spring-cloud的DiscoveryClient对象来获取和RestTemplate```对象相似,注意别导错坐标了是spring cloud提供的对象:

在这里插入图片描述
导入后如下:
在这里插入图片描述
如果导错坐标后会报错未发现报错的类,但是在IoC容器中,开发时也没注入spring cloud提供的DiscoveryClient对象啊,原因是使用了@EnableEurekaClient注解,已注入了org.springframework.cloud.client.discovery.DiscoveryClient对象。

在这里插入图片描述

org.springframework.cloud.client.discovery.DiscoveryClient对象提供了5个方法,
在这里插入图片描述

//实现类的功能描述,一般用在HealthIndicator的打印日志中
	String description();
	//根据服务Id获取对应的服务实例集合
	List<ServiceInstance> getInstances(String serviceId);
	//获取所有的服务Id
	List<String> getServices();

调用getInstances方法获取所有服务,注意服务不止有一个,同一个服务可能存在与不同服务器,或不同端口上,因此获取是一个集合。

ServiceInstance对象包含一个服务的基本信息:

public interface ServiceInstance {
    
	//实例Id
	default String getInstanceId() {
    
		return null;
	}
	//服务Id
	String getServiceId();
	//主机名或地址
	String getHost();
	//端口号
	int getPort();
	//是否使用安全协议HTTPS
	boolean isSecure();
	//服务的URL
	URI getUri();
	//服务实例相关的元数据
	Map<String, String> getMetadata();
	//使用方案,一般表示协议,比如http或https
	default String getScheme() {
    
		return null;
	}

}

想了解更多服务的实例对象可以参考该文章SpringCloud源码学习笔记Eureka客户端感谢作者@那些着急的人

由于只启动了一个服务,因此集合只有一个元素:
在这里插入图片描述

使用DiscoveryClient对象从注册中心获取服务的相关信息:

@RestController
@RequestMapping(value = "/role")
public class RoleController {
    


    @Autowired
    private DiscoveryClient discoveryClient;


    @GetMapping(value = "/product1")
    public String method(){
    
        List<ServiceInstance> product_service = discoveryClient.getInstances("product_service");
        for (ServiceInstance instance:product_service
             ) {
    
            System.out.println(instance);
        }
        return "ok";
    }
}

在这里插入图片描述
在这里插入图片描述

从运行结果可以看出,已经获取了服务的IP地址,因此可以将编写服务时硬编码的部分替换掉:

...
List<Role> roles =restTemplate.getForObject("http://localhost:8082/role/test",List.class);
...

此时http://localhost:8080相关信息都可以从注册中心获取的ServiceInstance中得到(启动另一个服务作为例子order_service):

@RestController
@RequestMapping(value = "/order")
public class OderController {
    

    @Autowired
    private UserService userService;

    @Autowired
    private RestTemplate restTemplate;

    //服务调用
    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/roles")
    public List<User> method1(){
    
        List<User> users = userService.selectColumn();
        return users;
    }

    @GetMapping(value = "/order_role")
    public List<Role> method2(){
    
        List<Role> roles =restTemplate.getForObject("http://localhost:8082/role/test",List.class);
        return roles;
    }


    @GetMapping(value = "/order_role1")
    public List<Role> method3(){
    
        //获取一个服务的实例
        //服务实例的赋值对象是ServiceInstance

        List<ServiceInstance> service_list = discoveryClient.getInstances("product_service");

        ServiceInstance instance = service_list.get(0);
        System.out.println(instance.getHost());
        System.out.println(instance.getUri());
        System.out.println(instance.getPort());

        List<Role> list = restTemplate.getForObject("http://"+instance.getHost()+":"+instance.getPort()+"role/test",List.class);

        return  list;
    }


}

该控制器有三个接口/roles为原始api、/order_role为模拟微服务api、/order_role1为微服务api,他们实现相同的功能。

启动两个服务:

在这里插入图片描述

在这里插入图片描述

原始api:
在这里插入图片描述
模拟微服务api:
在这里插入图片描述

微服务api:
在这里插入图片描述
哈哈哈,竟然报错了,看到状态码是500,就放心了,至少思路没问题。回到eureka后台发现了问题:

在这里插入图片描述
首先,ipaddr不是localhost,然后Status显示的也是显示的电脑名。原因在于:

eureka.instance配置下:

  • hostname即主机名不配置的话默认为电脑名,

  • instanceID不配置的话默认值为主机名+服务名+端口,

  • prefer-ip-address表示猜测主机名(hostname)为ip形式,不配置的话默认为false。

服务模块没有配置hostname导致地址不对,默认是电脑名且随机分配一个静态ip,所以服务器错误。对每个服务配置eureka.instance.hostname=localhost,再配置eureka.instance.instance-id=${eureka.instance.hostname}:${spring.application.name}:${server.port}上线时再将ip改为服务器地址。

# 数据源及驱动
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/smbms?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=root

# 端口
server.port=8081

# 关联注册中心

eureka.client.service-url.defaultZone=http://localhost:9000/eureka/

# 配置eureka的状态显示

eureka.instance.hostname=localhost
eureka.instance.instance-id=${
    eureka.instance.hostname}:${
    spring.application.name}:${
    server.port}

# 使用ip地址注册
eureka.instance.prefer-ip-address=true

# 配置服务的名称
spring.application.name=order_service

修改各个服务的配置生效:

在这里插入图片描述
该部分参考于Eureka Server实例状态一直显示主机名问题感谢作者!

接下来解决ipAddr显示的主机ip而不是localhost的问题:

# 忽略网卡的影响
#Npcap Loopback Adapter:为忽略的多网卡对注册中心注册的影响
spring.cloud.inetutils.ignored-interfaces[0]=Npcap Loopback Adapter

# 配置服务ip地址为localhost
eureka.instance.ip-address=localhost

在这里插入图片描述
再重新访问微服务api:

在这里插入图片描述

再会看代码:
在这里插入图片描述
服务的ip是注册中心自动完成的,获取也是,url的后缀是特定的,注册中心负责完成服务的注册与获取。

注册中心只是微服务的一个小分支,微服务时一个庞大的生态,各种组件支持解决不同的问题。

本案例仅简单介绍微服务。这些服务位于同一模块下。每个模块都是一个独立的spring boot程序。独立的Spring Boot程序也可以通过配置注册到注册中心,获取实际的技术核心。还有很多包括安全和过滤网关、配置中心、消息总线、监控和维护等。

期待下次更新吧!
. . .

相关推荐

额外说明

初始化块、final修饰符和Java抽象类、接口

一、初始化块根据是否使用static修饰分为两类: 不使用static修饰的是初始化块 使用static修饰的是静态初始化块 初始化块: 1、初始化块相当于是对构造器的补充用于创建对象时给对象的初始化,在构造器之前执行。 2、如果一段初始化代码对所有构造

额外说明

常用颜色英文名称

cyan:青色        indigo blue:蓝色 green:绿色 purple:紫色 yellow:黄色 red:红色 pink:粉红色 palegoldenrod :苍麒麟色 palegreen :苍绿色 paleturquoise: 苍绿

额外说明

使用JXL、HSSF、XSSH操作Excel数据

说明:的确是用JXL、HSSF、XSSF三种方式导入、导出Excel数据,但是跟所用项目的业务有所关联,摘出来比较麻烦,我就直接贴代码了。当给自己一个备份吧。   目前我知道的、会用的用来处理Excel的也就JXL和POI两种,JXL是用来处理Excel

额外说明

Company management技能

MBA 工商管理硕士 管理学 投资 市场 人力 企业 会计 财务 经济学 法律 公司法 税法 反不正当竞争法 价格法 五险两金 指用人单位给予劳动者的几种保障性待遇的合称 养老保险(为退休后的生活保障); 失业保险(为暂时失业的员工提供保障); 医疗保险

额外说明

C#中的ArrayList类详解

目录 一、ArrayList类定义 二、ArrayList类与数组的区别 三、ArrayList类对象的声明 1、默认的构造器 2、用一个ICollection对象来构造 3、用指定的大小初始化内部的数组 四、ArrayList常用属性 五、ArrayL

额外说明

CTFHub - 密码口令

CTFHub - 密码口令 – 弱口令 1.弱口令 工具:burpsuite 抓包 发送到爆破模块。字典用常用密码就行 结果: 2. 默认密码 常见的网络安全设备默认密码: 设备 默认账号 默认密码 深信服产品 sangfor

额外说明

每日博客【6】

1.字母大小写互换 #include <stdio.h> int main() { char a; while(scanf("%c",&a)!=EOF){ getchar();//因为是读取%c字符会把回车键也读

额外说明

安卓案例:安卓对话框演示

文章目录 一、对话框概述 二、案例演示 (一)运行效果 (二)涉及知识点 (三)实现步骤 1、创建安卓应用【DialogDemo】 2、将背景图片拷贝到drawable目录 3、主布局资源文件activity_main.xml 4、自定义对话框布局资源文

额外说明

EduSoho网校系统 增加微信公众号服务号,微信通知模板

微信通知开发业务 代码分析 通知模板 src/AppBundle/扩展/ExtensionManager.php $this->messageSubscribeTemplates = array_merge($this->messageSubscrib

ads via 小工具