返回随笔Java全栈
进行中ENGINEERING NOTE

SpringCloud 分布式

记录 Eureka 注册中心、服务生产者与消费者、心跳检测和客户端配置,持续整理 SpringCloud 微服务体系。

SpringCloud微服务

Eureka 注册中心

在微服务系统中,各个服务会动态地启动、停止或扩容,服务的地址和端口也可能随时变化。Eureka 提供一个“电话簿/注册中心”的角色。

生产者:服务提供者 消费者:服务使用者 每个生产者或消费者启动时,会将地址和元数据在Eureka注册。 当其他服务想要调用时就会查询Eureka,不需要写死端口和地址。服务会定期向Eureka发送心跳以检测可用性。

配置Eureka服务端

  • 创建Eureka项目并引用Eureka依赖
org.springframework.cloud spring-cloud-starter-netflix-eureka-server ``` - 配置Eureka Eureka本身就是一个Eureka服务,它需要在Euerka中注册,所以既需要指定服务端口也需要指定在eureka中注册的端口和地址。 ```yaml server: port: 10086

spring: application: name: eureka-server eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka ```

配置Eureka客户端

  • 创建Eureka项目并引用Eureka依赖(注意这里是client)
org.springframework.cloud spring-cloud-starter-netflix-eureka-client ``` - 配置Eurek ```yaml spring: application: name: order-server eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka ``` ## 服务发现 - 修改访问路径,用服务名代替ip和端口: ```java String url = "http://servername/user" ``` - 在RestTemplate上增加负载均衡注解,使得它可以解析上面的url为一个实例列表。 ```java @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } ``` # Ribbon 负载均衡 Ribbon是一个**客户端**负载均衡器,它用于解决服务调用时的负载均衡问题。 它和传统的服务端负载均衡不同,它将负载均衡放在客户端。在调用服务之前,会从注册中心(例如Eureka)中获取到服务的多个实例列表,然后按策略选择一个示例发起请求。 Ribbon有多种均衡策略,例如RoundRobnRule(轮询机制),RandomRule(随机机制)等。上面提到的RoadBalance就是Ribbon的一个注解。 # Nacos 注册中心 **Nacos** 是阿里巴巴开源的一个 **服务发现与配置管理平台**,类似于Eureka。 ## 服务分级存储模型 Nacos将实例按照地域划分成了集群,例如本地集群,南京集群等。由于跨集群调用服务延迟较高,有必要将每个集群配置调用优先级。 ```yaml spring: cloud: nacos: server-addr: localhost:8848 discovery: cluster-name: 南京 ``` ## NacosRule 负载均衡 Nacos集成了许多负载均衡策略,例如NacosRule,它会优先寻找与自己同集群的服务。 ```yaml userservice: ribbon: NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule ``` 同样,Nacos还能单独配置每一个地域实例的权重,权重高的实例将被优先访问。如果权重为0,则完全不会被访问。 ## Nacos 环境隔离 可以配置实例的namespace,可以将两个实例配置为不同namespace,不同的namespace中的实例无法访问。每个namespace都有唯一的id,配置时配置的也是id而非名称。 ## Nacos和Eureka的区别 - 对于生产者:当生产者挂掉之后,Eureka会立即从注册中心中删除这一实例,而Nacos会将其标记为不健康,并等待其恢复,并不会直接将其删除。 - 对于消费者:消费者每隔一段时间会向注册中心请求实例列表,Eureka仅会被动接受请求,而Nacos会在服务列表有更新时主动向消费者推送。 # Nacos 配置管理 Nacos可以用于配置管理,可以将一些经常会更改的配置交给Nacos管理,当这些配置有更新时,Nacos会通知服务更新配置。例如,可以将日期格式配置交由Nacos管理: ```yaml pattern: dateformat: yyyy-MM-dd HH:mm:ss ``` 在程序启动过程中,需要先获取到Nacos的地址才能进行配置管理,但是引入Nacos后,会先从Nacos获取配置,再获取application.yml的配置,这是程序并不知道Nacos的地址是什么。 所以,需要在微服务中添加bootstrap.yml文件,用于配置Nacos地址等信息。这个文件的加载优先级较高,会在获取Nacos配置之前加载。 # Gateway 网关 在生产环境中,不可能将微服务的各个实例直接暴露给外部用户,所以需要网关来实现转发。Spring提供了两个网关gateway和zuul,前者基于Springflux,为响应式结构,较新;后者基于阻塞式编程,是较为陈旧的技术。 使用网关需要编写路由配置和nacos地址。网关也作为一种可被发现的nacos服务,所以需要在nacos中注册。 ```yaml server: port: 10010 # 网关端口 spring: application: name: gateway # 服务名称 cloud: nacos: server-addr: localhost:8848 # nacos地址 gateway: routes: - id: user-service # 网关id,需要唯一 uri: lb://userservice # 路由的目标地址 lb为负载均衡,后面为服务名称 predicaties: # 路由断言,判断请求是否符合路由规则的条件 - Path=/user/** # 按照路径匹配,以/user/开头就符合要求 ``` ## 路由断言工厂 在配置文件中写明的断言规则是字符串,这些字符串会被断言工厂所读取,然后转换为真正的判断条件。 路由断言工厂提供了11种不同的判断条件。 ## 过滤器配置 过滤器可以对经过路由的请求或响应做加工处理,比如添加请求头。配置在路由下的过滤器只对当前路由的请求生效。也可以使用defaultFilters添加对所有路由都生效的过滤器。 ```yaml gateway: routers: - id: user-service uri: lb://userservice filters: # 单路由过滤器 AddRequestHeader=Cappuccino default-filters: # 默认过滤器(针对所有路由) - AddRequestHeader=Cappuccino ``` ## 全局过滤器 全局过滤器可以实现自定义的过滤器。它不同于默认过滤器。默认过滤器只能使用几种定义好的逻辑,而全局过滤器可以自行编写代码逻辑。 想要实现全局过滤器,需要实现GlobalFilter接口。 ```java public class AuthorizeFilter implements GlobalFilter { public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); MultiValueMap params = request.getQueryParams(); String auth = params.getFirst("authorization"); if ("admin".equals(auth)) { //放行 return chain.filter(exchange); } exchange.getResponse().setStatusCode(401); //拦截请求 return exchange.getResponse().setComplete(); } } ``` # RabbitMQ