部分文字摘录自:https://gitbook.cn/books/5d82...
微服务架构的定义,就是将原来的单体应用按义务范围来划分为多个小的模块,每个微服务运行在自己的进程中,相互不产生影响,完全自动化独立部署,并使用轻量级机制通信,通常是 HTTP RESTUFUL API,可对各微服务进行集中管理。
Spring Cloud 包含如下的核心组件:
- 服务注册与发现:Eureka、Consul、Zookeeper
- API 网关:Zuul、Spring Cloud Gateway
- REST 调用:Feign
- 负载均衡:Ribbon
- 容错处理:Hystrix
- 链路追逐:Sleuth、Zipkin
- 配置管理:Config
服务注册与发现组件主要解决两个问题:服务注册和服务发现。
- 服务注册:服务实例将自身服务信息注册到注册中心。这部分服务信息包括服务所在主机 IP 和提供服务的 Port,以及暴露服务自身状态以及访问协议等信息。
- 服务发现:服务实例请求注册中心获取所依赖服务信息。服务实例通过注册中心,获取到注册到其中的服务实例的信息,通过这些信息去请求它们提供的服务
API 网关可以做一下事情:
- 统一入口
- 统一限流
- 统一认证鉴权
- 动态路由制定和修改
- 负载
- 服务容错降价
- 版本控制
- 统一监控日志记录
- 协议转换:如 HTTP => RPC 协议
- 缓存
- 静态
- 灰度:线上灰度部署,可以减小风险
REST 调用的方式。一般情况我们发送一个 HTTP 请求,可能是采用完整域名或者 IP 加 URI 接口的方式,但是我们不可能为每个服务都分配一个域名,这是不现实的;我们也不可能直接通过 IP 的方式调用,一是 IP 可能会太多,最主要的是 IP 会经常变动,那样又会改动代码,多麻烦。
有了 Feign 这个工具,这些问题都不存在了。
Feign 是一个声明式 WebService 客户端,旨在使编写 Java HTTP 客户端变得更容易。使用 Feign 能让编写的 WebService 客户端更加简洁,它的使用方法很简单,就是定义一个接口,然后在上面添加注解。
负载均衡
负载均衡好理解,我们的一个微服务为了提高性能可能会部署多台,这个时候就需要将压力分散到每台服务器上,Ribbon 就是来干这个事情的。
容错处理
随着业务的扩展,服务的数量也会随之增多,逻辑会更加复杂,一个服务的某个逻辑需要依赖多个其他服务才能完成。一旦一个依赖不能提供服务很可能会产生雪崩效应,最后导致整个服务不可访问。
Hystrix 熔断就是为了避免服务的雪崩产生,当 A 服务调用 B 服务时,如果 B 服务不能快速响应,Hystrix 就会在一定时间内做熔断处理,放回默认为值。
链路追逐、配置管理
链路追踪
主要是为了方便排查问题,我们的一个服务可能要调用多个微服务才能完成所有操作,当某个服务报错出现异常了怎样快速定位是哪个服务报错了呢?我们不可能把所有的服务日志都打开观察吧,链路追踪就是为了方便我们查看微服务的调用链,让我快速定位那个服务出现了异常。
常见的链路追踪有 Sleuth、Zipkin、Skywalking 等。
配置管理
我们的项目里面除了常见的配置数据库、缓存等外,可能还有很多的其他配置,比如:某些三方服务域名,账号密钥等。当然这些配置也完全可以都放在项目里面的配置文件中,但是当你要修改配置,可能就要重启服务才能使新的配置生效。
有办法可以动态的修改配置,并且在不重启服务的情况下让配置生效吗?肯定有。Spring Cloud Config 就帮我们实现了我们想要的功能,还有功能更强大的配置管理服务,携程开源的 Apollo② 分布式配置中心,你指的拥有。
容器化部署
当我们在使用微服务的时候,那么有一个问题一定会困扰我们,那就是项目的测试和部署。
因为在单体应用下,部署项目很简单,直接打包启动就可以了,而对于微服务来说,因为有各个组件的存在所以让测试和部署都变得很麻烦,而且有时还因为环境配置等差异导致意向不到的问题。而容器化是微服务部署一把利剑,统一标准,让我的环境高度一致,方便我们快速的部署上线应用。
Eureka
引入依赖
<!-- Eureka Server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- Spring boot admin监控 -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
创建项目启动类
@EnableAdminServer
@EnableEurekaServer
@SpringBootApplication
public class EurekaDiscoveryApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaDiscoveryApplication.class, args);
}
}
添加配置
# 服务端口
server.port=10000
# 服务名称
spring.application.name=eureka-with-monitor
# 暴露的管理端点,星号标识全部
management.endpoints.web.exposure.include=*
# 设置Spring boot admin 的context上下文,避免和Eureka冲突
spring.boot.admin.context-path=admin
# 是否获取注册的服务
eureka.client.fetch-registry=false
# Eureka服务地址
eureka.client.service-url.defaultZone=http://localhost:${server.port}/eureka
# Spring boot admin监控地址
spring.boot.admin.client.url=http://localhost:${server.port}/admin
# 以IP方式注册到Eureka
eureka.instance.prefer-ip-address=true
到此带有监控功能的 Eureka 服务就建立好了,在浏览器中访问 http://localhost:10000 看看吧。
- Eureka 界面:http://localhost:1000
- 监控界面:http://localhost:10000/admin
在各个服务中配置Eureka
(1) 加入依赖
<!-- spring boot admin监控客户端 -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<!-- Eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
应用启动类添加:@EnableDiscoveryClient
application.properties 添加如下配置:
# 服务端口
server.port=10020
# 应用名称
spring.application.name=user-service
# Eureka服务地址
eureka.client.service-url.defaultZone=${EUREKA_SERVER_ADDRESS:http://localhost:10000/eureka}
# Spring boot admin监控服务地址
spring.boot.admin.client.url=${EUREKA_SERVER_ADDRESS:http://localhost:10000/admin}
# 暴漏端点,星号标识所有
management.endpoints.web.exposure.include=*
# 以IP方式注册到Eureka
eureka.instance.prefer-ip-address=true
这里得EUREKA_SERVER_ADDRESS,容器化部署时以环境变量传入。
docker run -p 10000:10000 -d \
-e "EUREKA_SERVER_ADDRESS=http://192.168.2.127:10000/eureka" \
--name service-eureka \
service-eureka:latest
Feige使用
Feign 的主要功能是提供了一种可以像 Java 之间方法调用的方式来进行 HTTP 服务之间的调用,它主要屏蔽了 HTTP 接口请求方式的复杂性。
加上依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
在 SpringBoot Application上声明 @EnableFeignClients
在application.properties中配置 Eureka客户端的配置
server.port=8762
spring.application.name=ORDERSERVICE
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
在 RestTemplateConfig 构建方法上声明 @LoadBalanced
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate buildRestTemplate() {
return new RestTemplate();
}
}
创建调用接口,并在接口上声明 @FeignClient(name="PRODUCTSERVER") 其中name的值是调用服务的名称。在声明调用的方法 @RequestMapping()中配置 URL 和商品服务 API 接口一样即可
@FeignClient(name="PRODUCTSERVER")
public interface ProductClient {
@GetMapping("/product/{id}")
public Product productInfo(@PathVariable(name="id")Long productId);
}
开始编写调用的测试类,在ProductController 中引入 PersonClient 然后调用ProductClient 调用方法即可
@RestController
public class ProductController {
@Autowired
private ProductClient personClient;
@RequestMapping("/product/{id}")
public Product productInfo(@PathVariable(name="id")Long productId) {
Product product = personClient.productInfo(productId);
return product;
}
}
zuul网关
参考文章:https://gitbook.cn/books/5dbb...
在微服务架构中,我们的系统被拆分成了多个子服务,这些服务之间互相协作同时对外提供服务。那么,服务使用方如何调用我们的服务呢?如果我们将每个服务单独暴露出去,这对于服务调用方将是一个巨大的灾难。同时对于我们服务提供方来说,大量的暴露服务,服务管理工作将会成为一个大问题。由此,微服务网关就诞生了。它是微服务体系对外暴露的唯一服务,服务调用方统一与我们的网关服务进行交互,所有请求由网关转发到微服务架构中的具体服务提供方,服务调用结束后再由网关将请求结果返回给客户端。
网关的几个应用场景:
1. 安全认证
如果没有网关统一对接外部调用请求,那么我们需要为每个服务单独的增加权限控制功能。有了网关以后我们就可以对所有的请求在网关层对请求进行安全认证,如果认证失败,直接拒绝请求。
2. 日志记录
统一在网关层对微服务体系的所有请求进行日志记录,便于后续的分析统计。
3. 服务监控
在网关层我们可以对所有的请求进行质量监控,并且对于一些异常的请求可以进行熔断处理,当某些服务负载过重的时候可以进行降级处理。基本上一些横跨多个服务的切面逻辑我们都可以统一在网关层做处理。
4. 服务线上数据模拟
假设我们有一些业务问题要进行 Debug 定位问题,我们可以在网关层面做特殊逻辑处理,将用户流量复制一份转发到测试服务,这样就很容易的可以模拟出线上环境数据,便于调查问题。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。