相关基础
Maven
坐标:
- groupId: 工程组的标识。
- artifactId: 工程的标识。
- version: 工程版本号。
相关命令:
- mvn -v 查看maven版本
- mvn compile 编译,将java源文件编译成class文件
- mvn test 执行test目录下的测试用例
- mvn package 打包,将java工程打成jar包
- mvn clean 清理环境,清除target文件夹
相关特性:
- 传递依赖 项目引用了一个jar包,而该jar包又引用了其他jar包,maven会把直接引用和间接引用的jar包都下载到本地。
- 排除依赖:只想下载直接引用的jar包 (需要给出排除的jar包)
1 | <exclusions> |
- 依赖冲突 项目中多个jar同时引用了相同的jar时,会产生依赖冲突。有以下两种避免冲突的策略:
- 短路优先 引用路径短的优先
- 声明优先 引用路径相同时,在pom.xml文件中谁先被声明,就使用谁。
多模块项目/聚合
父模块pom文件的配置:packing类型必须是pom
1
2
3<groupId>xxxgroupId>
<artifactId>xxxartifactId>
<packaging>pompackaging>聚合子模块:使用modules标签
1
2
3
4
5<modules>
<module>xxxmodule>
<module>xxxmodule>
<module>xxxmodule>
modules>父模块统一管理依赖包: 使用dependencyManagement标签
子模块需要在pom文件中声明父模块: 使用parent模块
项目右侧将maven的pom文件导入,重新reimport,便可以跳转类。
EurekaServer的开发
单节点EurekaServer
1 | //两个注解表明是EurekaServer,是springboot应用启动程序 |
添加配置文件application.yml
1 | spring: |
多节点EurekaServer
修改配置文件
1 | spring: |
修改hosts文件
1 |
|
Eureka相关内容
核心功能
- Service Registry(服务注册)
- Service Discovery(服务发现)
基本架构
Eureka 由三个角色组成:
- Eureka Server(这一章实现的功能),提供服务注册与发现
- Service Provider,服务提供方,将自身服务注册到 Eureka Server 上,从而让 Eureka Server 持有服务的元信息,让其他的服务消费方能够找到当前服务
- Service Consumer,服务消费方,从 Eureka Server 上获取注册服务列表,从而能够消费服务
- Service Provider/Consumer 相对于 Server,都叫做 Eureka Client
高可用
问题说明:单节点的 Eureka Server 虽然能够实现基础功能,但是存在单点故障的问题,不能实现高可用。因为 Eureka Server 中存储了整个系统中所有的微服务的元数据信息,单节点一旦挂了,所有的服务信息都会丢失,造成整个系统的瘫痪。
解决办法:搭建 Eureka Server 集群,让各个 Server 节点之间互相注册,从而实现微服务元数据的复制/备份,即使单个节点失效,其他的 Server 节点仍可以继续提供服务
元信息
- Eureka Server中维护了系统中服务的,其中有两种:标准元数据和自定义元数据。
标准元数据:主机名、IP地址、端口号、状态页和健康检查等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。
自定义元数据:可以使用eureka.instance.metadata-map配置,这些元数据可以在远程客户端中访问,但是一般不改变客户端行为,除非客户端知道该元数据的含义。
如果我们在启动 Client(简单认为就是一个微服务)的时候,如果此时配置了错误的 Eureka Server 发现地址,或 Eureka Server 没有启动,那么,你会发现,Client 可以正常启动,但是不能完成注册。会抛出如下异常信息。
1 | com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server |
这里的异常信息,其实就告诉了我们,Client 向 Eureka Server 发起注册的过程。我们看一看 DiscoveryClient.register 里面做了什么
源码路径:eureka-client-1.9.2-sources.jar!/com/netflix/discovery/DiscoveryClient.java
1 | /** |
instanceInfo 就是 com.netflix.appinfo.InstanceInfo 的对象实例,它被称作是 “应用实例信息”。所以,这个对象中包含的属性,最终会投递到 Eureka Server 中,也就是说,Eureka Server 维护的元信息就是 InstanceInfo 。
元信息的保存
- 其中,涉及到元信息的保存,可能是Eureka Server内部维护着一张表来记录这些元信息,Eureka服务器没有后端存储,但注册表中的服务实例必须发送心跳信号以保持其注册是最新的,所以这可能使内存中完成。客户端可能还拥有一个eureka注册的内存缓存,这样,client不必为每个服务请求都去注册表。
Client 向 Server 发起注册(Http 请求),那么Server 必须对外提供这个接口才可以。经过追踪 Server 端的源码(eureka-core-1.9.2-sources.jar),很容易可以找到 源码路径:com/netflix/eureka/resources/ApplicationResource.java,其中 addInstance 方法即实现了服务注册的功能(Server 端)。源码如下:
1 |
|
我们再去看 PeerAwareInstanceRegistry 的实现类:org.springframework.cloud.netflix.eureka.server.InstanceRegistry 的 register 方法的实现:
1 | public void register(final InstanceInfo info, final boolean isReplication) { |
继续看 AbstractInstanceRegistry 的 register 方法的实现:
1 | public void register(InstanceInfo registrant, int leaseDuration, boolean isReplication) { |
InstanceInfo 中的元数据信息存储在一个 ConcurrentHashMap 对象中。Eureka Server 使用了两层 Map 结构做存储,第一层的 key 存储服务名:InstanceInfo 中的 appName 属性,第二层 key 存储实例名:InstanceInfo 中的 instanceId 属性。
微服务架构以及网关介绍
微服务架构的两种方式:
- 点对点的方式:服务之间直接调用,每个微服务都开放Rest API,并调用其他微服务的接口。
- API-网关方式:业务接口通过API网关暴露,是所有客户端接口的唯一入口,微服务之间的通信也通过API网关。
Zuul 的生命周期:
Zuul 提供了服务网关的功能,可以实现负载均衡、反向代理、动态路由、请求转发等功能。Zuul 大部分功能都是通过过滤器实现的,Zuul 中定义了四种标准的过滤器类型,同时,还支持自定义过滤器。
- Pre filters:在请求路由之前被调用,实现身份验证,在集群中选择请求的微服务。
- Routing filters: 请求路由到微服务
- Post filters:响应http头,收集统一信息和指标。将响应微服务发送给客户端。在 route 和 error 过滤器之后被调用
- Error filters: 处理请求时发生错误时被调用。
网关启动程序的开发
1 | //开启网关代理 |
编写配置文件
1 | server: |
自定义网关过滤器
实现打印访问日志,记录访问的延迟,从请求到返回经历了多少时间的功能。
编写Pre filter
1 | import com.netflix.zuul.ZuulFilter; |
编写Post filter
1 | import com.netflix.zuul.ZuulFilter; |