03 微服务基本知识-微服务调用及运行过程
第十三课:微服务基本知识-微服务调用及运行过程
3. 微服务调用及运行过程
3.1 为什么分析微服务过程调用
在实际的项目中,微服务之间涉及到业务代码的部分,调用逻辑非常复杂,对于工程师而言,熟悉组件之间的调用关系,方便以后业务模块开发,集群部署与自动化编排过程中有非常大的帮助(基础),并且能够非常清楚哪些应用应该对外,哪些可以不用对外以及服务是怎样存活。
- 在微服务中涉及的组件:注册中心,配置中心,服务提供者,服务消费者,路由网关
3.1.1 本案例涉及的服务有以下几种
注册中心服务(nacos),配置中心服务(nacos),服务提供者(passport),服务消费者(restTemplate,Feign),路由网关服务(Spring Cloud Gateway)
3.2 组件服务调用基本流程
- 客户端浏览器输入url
- 访问网关负载均衡(7层,可以是nginx/haproxy)通过负载均衡分发请求到spring cloud gateway网关
- 网关在即受到来自负载均衡的请求之后,根据url地址匹配到服务名称,调用后台的restTemplate服务
- restTemplate在接收到来自网关的请求以后,通过注册中心查询到服务列表,将请求服务列表中的服务,最后返回结果。
3.3 组件内部接口调用流程
负载均衡->网关->消费者->服务提供者
3.4 微服务实战(单机部署)
3.4.1 运行微服务
安装java环境
将java安装包(jdk1.8.0_192.tar.gz)传到主机/usr/local/下并解压缩
编辑环境变量/etc/profile
vim /etc/prolfie
export JAVA_HOME=/usr/local/jdk1.8.0_192
export JRE_HOME=/${JAVA_HOME}/jre
export PATH=${JAVA_HOME}/bin:$PATH
#应用
source /etc/profile
3.4.2 安装nacos(单机)
下载注册中心nacos
wget https://github.com/alibaba/nacos/releases/download/1.1.4/nacos-server-1.1.4.tar.gz
tar zxvf nacos-server-1.1.4.tar.gz
cd nacos/bin
sh startup.sh -m standalone
登陆访问页面
http://192.168.68.152:8848/nacos
username:nacos
password:nacos
导入配置文件
nacos_config_provider.zip ----> provider-passport-config.yaml
nacos_config_gateway.zip ----> spring-cloud-gateway.yaml
可以从页面修改配置文件中注册中心的IP地址
spring-cloud-gateway.yaml
server-addr: 192.168.68.152:8848
file-extension: yaml
config:
server-addr: 192.168.68.152:8848
provider-passport-config.yaml
server-addr: 192.168.68.152:8848
生产使用集群模式(至少3个节点)
- 安装mysql5.7.25(主从)
- 导入数据库(nacos-mysql.sql)
- 修改配置文件(application.properties cluster.conf)
- 启动(sh startup.sh)
3.4.3 安装redis
yum install epel-release -y
yum install redis -y
#修改密码
vim /etc/redis.conf
requirepass 123456
bind 0.0.0.0
#开机启动
systemctl enable redis
systemctl restart redis
systemctl status redis
查看端口监听
[root@localhost ~]# netstat -lantup | grep 6379
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 12850/redis-server
修改配置文件spring-cloud-gateway.yaml
redis:
host: 192.168.68.152
port: 6379
password: 123456
3.4.4 后台服务provider-passport
上传测试包
mkdir springcloud && cd springcloud
[root@localhost springcloud]# ll
total 449792
-rw-r--r-- 1 root root 91330721 Aug 26 10:18 consumer-feign-passport-0.0.1-SNAPSHOT.jar
-rw-r--r-- 1 root root 90430214 Aug 26 10:28 consumer-passport-0.0.1-SNAPSHOT.jar
-rw-r--r-- 1 root root 105609972 Aug 26 12:27 gateway-0.0.1-SNAPSHOT.jar
-rw-r--r-- 1 root root 49134278 Aug 26 10:27 monitor-0.0.1-SNAPSHOT.jar
-rw-r--r-- 1 root root 33651884 Aug 26 10:24 passport-demo-0.0.1-SNAPSHOT.jar
-rw-r--r-- 1 root root 90419589 Aug 26 12:14 provider-passport-0.0.1-SNAPSHOT.jar
3.4.4.1 运行provide passport
java -Dspring.cloud.nacos.discovery.server-addr=192.168.68.152:8848 \
-Dspring.cloud.nacos.config.server-addr=192.168.68.152:8848 \
-jar provider-passport-0.0.1-SNAPSHOT.jar
3.4.4.2 服务注册
从页面查看我们刚才启动的passport服务已经注册到注册中心
3.4.4.3 访问后台服务接口
http://192.168.68.152:8086/v1/auth/login
返回json内容如下:
{
msg: "demo passport api",
api: "/v1/auth/login",
type: "passportProvider",
status: 200
}
http://192.168.68.152:8086/passport
返回json内容如下:
{
msg: "后台服务passport",
api: "/passport",
type: "autoNacosConfig",
status: 200
}
2.4.4.4 验证配置中心修改配置功能
通过nacos页面修改配置文件provider-passport-config.yaml的内容后,再次调用后台服务接口,可以看出我们通过配置中心修改配置以后并不需要重启服务,配置即时生效。
#修改msg字段
data:
msg: '后台服务passport-修改配置测试'
再次调用接口http://192.168.68.152:8086/passport
{
msg: "后台服务passport-修改配置测试",
api: "/passport",
type: "autoNacosConfig",
status: 200
}
注意:并不是所有的配置可以在不重启服务的情况下生效,比如数据库。
查看passport服务日志可以看到配置变更以后重新生效的过程
如果能够使用nacos注册到注册中心则使用临时实例,否则使用永久实例
类型 | 服务端 | 客户端 |
---|---|---|
主动发送 | 配置文件发送,统一更新 | 发送心跳 |
被动接受 | 心跳信息 | 配置文件 |
客户端: |
2020-08-27 09:50:24.077 INFO 20140 --- [ing.beat.sender] com.alibaba.nacos.client.naming : [BEAT] [] [] send beat to server: {"cluster":"DEFAULT","dom":"provider-passport","ip":"192.168.68.152","metadata":{"preserved.register.source":"SPRING_CLOUD","content":"/"},"port":8086,"weight":1.0}
企业部署nacos注册中心部署的建议:
- 几个环境几个注册中心(开发环境1台机器1个注册中心,生产环境3台机器(集群)1个注册中心,测试环境1台机器1个注册中心),几个环境几个配置文件(比如passport-config-dev.yaml,passport-config-test.yaml,passport-config-prod.yaml)
- 1个配置中心,不同的ns(不建议)
- tomcat瓶颈优化的方法:1.横向扩展,增加容器的数量。2.代码优化修改并发连接数。
3.4.5 运行消费者consumer-feign-passport服务
3.4.5.1 运行消费者feign服务
java -Dspring.cloud.nacos.discovery.server-addr=192.168.68.152:8848 \
-Dspring.cloud.nacos.config.server-addr=192.168.68.152:8848 \
-jar consumer-feign-passport-0.0.1-SNAPSHOT.jar
3.4.5.2 服务注册
再次通过nacos页面查看服务注册情况
3.4.5.3 访问消费者Feign服务接口
http://192.168.68.152:9092/v1/auth/login
{
msg: "demo passport api",
api: "/v1/auth/Feign controller",
type: "feign",
status: 200
}
http://192.168.68.152:9092/passport
{
msg: "后台服务passport-修改配置测试",
api: "/passport",
type: "feignPassport",
status: 200
}
3.4.6 运行消费者consumer-passport服务
3.4.6.1 运行消费者consumer-passport服务
java -Dspring.cloud.nacos.discovery.server-addr=192.168.68.152:8848 \
-Dspring.cloud.nacos.config.server-addr=192.168.68.152:8848 \
-jar consumer-passport-0.0.1-SNAPSHOT.jar
3.4.6.2 服务注册
通过nacos页面或者从服务日志可以看到注册成功
2020-08-27 10:41:27.177 INFO 21027 --- [ main] o.s.c.a.n.registry.NacosServiceRegistry : nacos registry, consumer-passport 192.168.68.152:9091 register finished
3.4.6.3 接口测试
http://192.168.68.152:9091/v1/auth/login
{
msg: "demo passport restTemplate /v1/auth/login api",
api: "{"msg":"demo passport api","api":"/v1/auth/consumer-passport","type":"passportProvider","status":200}",
type: "restTemplatePassport",
status: 200
}
http://192.168.68.152:9091/passport
{
msg: "demo passport restTemplate /passport api",
api: "{"msg":"后台服务passport-修改配置测试","api":"/passport","type":"autoNacosConfig","status":200}",
type: "restTemplatePassport",
status: 200
}
3.4.7 两种消费者调用的区别是什么
restTemplate和Feign的区别
在spring cloud 中有两种服务调用方式,一种是ribbon+restTemplate ,另一种是feign。相对来说,feign因为注解使用起来更简便。而restTemplate需要我们自定义一个RestTemplate,手动注入,并设置成LoadBalance。
内部调用:(内网相通)使用feign调用,调用方式为http://服务名/接口地址,比如:http://provider-passport/passport
跨地址/区域调用:(走外网调用)使用restTemplate调用,调用方式为http://服务IP地址/服务名称/接口地址,比如:http://192.168.68.152:8086/passport
我们在Java项目中调用接口有四种方式,分别是:
Httpclient
Okhttp
Httpurlconnection
RestTemplate
从消费者服务接口返回的内容与从passport提供者接口的内容一致,原理是访问消费者接口反向代理到提供者接口,获取返回内容。为什么要这么做的原因是如果后台有多个提供者的时候,消费客feign提供了负载均衡的作用。
3.4.8 运行网关服务
3.4.8.1 运行网关gateway服务
java -Dspring.cloud.nacos.discovery.server-addr=192.168.68.152:8848 \
-Dspring.cloud.nacos.config.server-addr=192.168.68.152:8848 \
-jar gateway-0.0.1-SNAPSHOT.jar
3.4.8.2 注册服务
同样的在nacos页面或者服务启动日志中可以看到服务注册成功信息
2020-08-27 11:19:37.475 INFO 22094 --- [ main] o.s.c.a.n.registry.NacosServiceRegistry : nacos registry, spring-cloud-gateway 192.168.68.152:9000 register finished
3.4.8.3 接口测试
通过gateway访问后台服务
通过consumer-feign-passport访问后台服务/v1/auth/login
正常请求feign调用
http://192.168.68.152:9000/consumer-feign-passport/v1/auth/login?token=1231
{
msg: "demo passport api",
api: "/v1/auth/Feign controller",
type: "feign",
status: 200
}
http://192.168.68.152:9000/consumer-feign-passport/passport?token=123123
{
msg: "后台服务passport-修改配置测试",
api: "/passport",
type: "feignPassport",
status: 200
}
正常请求restTemplate调用
http://192.168.68.152:9000/consumer-passport/v1/auth/login?token=122222
{
msg: "demo passport restTemplate /v1/auth/login api",
api: "{"msg":"demo passport api","api":"/v1/auth/consumer-passport","type":"passportProvider","status":200}",
type: "restTemplatePassport",
status: 200
}
http://192.168.68.152:9000/consumer-passport/passport?token=123123
{
msg: "demo passport restTemplate /passport api",
api: "{"msg":"后台服务passport-修改配置测试","api":"/passport","type":"autoNacosConfig","status":200}",
type: "restTemplatePassport",
status: 200
}
3.4.9 鉴权功能
我们在访问网关接口的时候,需要带token才能正常访问,否则会报非法请求
http://192.168.68.152:9000/consumer-feign-passport/v1/auth/login
{
code: 401,
cause: "Token字符串为空!",
message: "非法请求"
}
3.5 注册中心服务列表
服务必须存在与服务列表才能被调用
3.6 微服务治理
3.6.1 服务熔断处理
在正常服务访问的情况下,后台服务不可用的情况下,或出现500的错误,返回客户端很不友好,并且接口之间的调试比较困难,因为不知道后台服务发生了什么错误。
将后台passport服务停掉模拟后台服务挂掉不可访问的状态,分别查看有服务熔断和没有服务熔断的接口返回
有服务熔断的返回:
http://192.168.68.152:9000/consumer-feign-passport/v1/auth/login?token=122222
{
msg: "feign 调用后台认证服务接口(/v1/auth/login)失败, 服务熔断处理.",
type: "feignFallBack",
status: 400
}
http://192.168.68.152:9000/consumer-feign-passport/passport?token=123123
{
msg: "调用后台认证接口(/passport)失败, 服务熔断处理.",
type: "feignFallBack",
status: 400
}
没有服务熔断的返回
http://192.168.68.152:9000/consumer-passport/v1/auth/login?token=122222
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Aug 27 14:13:04 CST 2020
There was an unexpected error (type=Internal Server Error, status=500).
No message available
3.6.2 服务熔断的实现方法
- 代码实现
- 集群实现(服务网格)
为什么会熔断?
- 服务调用超时
- 服务异常宕机
- 优雅处理异常
3.6.3 调用链
介绍
http://skywalking.apache.org/zh/blog/2019-03-29-introduction-of-skywalking-and-simple-practice.html
使用APM分析接口调用过程
注意:
- 采样率与损耗(默认是-1,每个3秒)
- 后台存储保存数量h2(5000条)
服务端启动
mkdir /root/apm && cd /root/apm
wget https://archive.apache.org/dist/skywalking/6.1.0/apache-skywalking-apm-6.1.0.tar.gz
tar zxvf apache-skywalking-apm-6.1.0.tar.gz
cd apache-skywalking-apm-bin/bin
sh startup.sh
正常启动以后通过页面访问http://192.168.68.152:8080/
用户名:admin
密码:admin
配置文件 application.yml
#启用ES的时候取消以下注释
# clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
# indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:2}
# indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:0}
# bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:2000} # Execute the bulk every 2000 requests
# bulkSize: ${SW_STORAGE_ES_BULK_SIZE:20} # flush the bulk every 20mb
# flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:10} # flush the bulk every 10 seconds whatever the number of requests
# concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2} # the number of concurrent requests
# metadataQueryMaxSize: ${SW_STORAGE_ES_QUERY_MAX_SIZE:5000}
# segmentQueryMaxSize: ${SW_STORAGE_ES_QUERY_SEGMENT_SIZE:200}
#注释掉h2模式配置
h2:
driver: ${SW_STORAGE_H2_DRIVER:org.h2.jdbcx.JdbcDataSource}
url: ${SW_STORAGE_H2_URL:jdbc:h2:mem:skywalking-oap-db}
user: ${SW_STORAGE_H2_USER:sa}
metadataQueryMaxSize: ${SW_STORAGE_H2_QUERY_MAX_SIZE:5000}
服务端启动
拷贝agent目录到需要监测的设备上,本次为单机部署,故只需要将agent目录拷贝到指定目录即可,当然也可以不拷贝到指定路径,但是在启动服务的时候需要指定agent所在的绝对路径。
cp -r agent/ /root/springcloud/
启动provider passport服务
java -Dspring.cloud.nacos.discovery.server-addr=192.168.68.152:8848 \
-Dspring.cloud.nacos.config.server-addr=192.168.68.152:8848 \
-javaagent:agent/skywalking-agent.jar \
-Dskywalking.agent.service_name=provide-passport \
-Dskywalking.collector.backend_service=192.168.68.152:11800 \
-jar provider-passport-0.0.1-SNAPSHOT.jar
启动服务日志可以看到加载agent的信息
DEBUG 2020-08-27 16:34:03:616 main AgentPackagePath : The beacon class location is jar:file:/root/springcloud/agent/skywalking-agent.jar!/org/apache/skywalking/apm/agent/core/boot/AgentPackagePath.class.
INFO 2020-08-27 16:34:03:619 main SnifferConfigInitializer : Config file found in /root/springcloud/agent/config/agent.config.
...
2020-08-27 16:36:37.101 INFO 1080 --- [ main] o.s.c.a.n.registry.NacosServiceRegistry : nacos registry, provider-passport 192.168.68.152:8086 register finished
测试访问passport服务,查看skywalking是否可以获取到访问信息
for i in `seq 10000` ;do curl 192.168.68.152:8086/passport ;echo "";done
从页面查看信息
同样的操作我们将消费者服务和网关服务也加入到skywalking的监测下
重新启动feign服务
java -Dspring.cloud.nacos.discovery.server-addr=192.168.68.152:8848 \
-Dspring.cloud.nacos.config.server-addr=192.168.68.152:8848 \
-javaagent:agent/skywalking-agent.jar \
-Dskywalking.agent.service_name=consumer-feign-passport \
-Dskywalking.collector.backend_service=192.168.68.152:11800 \
-jar consumer-feign-passport-0.0.1-SNAPSHOT.jar
重新启动restTemplate consumer-passport服务
java -Dspring.cloud.nacos.discovery.server-addr=192.168.68.152:8848 \
-Dspring.cloud.nacos.config.server-addr=192.168.68.152:8848 \
-javaagent:agent/skywalking-agent.jar \
-Dskywalking.agent.service_name=consumer-passport \
-Dskywalking.collector.backend_service=192.168.68.152:11800 \
-jar consumer-passport-0.0.1-SNAPSHOT.jar
重新启动gateway服务
java -Dspring.cloud.nacos.discovery.server-addr=192.168.68.152:8848 \
-Dspring.cloud.nacos.config.server-addr=192.168.68.152:8848 \
-javaagent:agent/skywalking-agent.jar \
-Dskywalking.agent.service_name=gateway \
-Dskywalking.collector.backend_service=192.168.68.152:11800 \
-jar gateway-0.0.1-SNAPSHOT.jar
将上述4个服务全部重启以后,再次在页面查看,可以看到skywalking已经监测到这4个服务。
测试服务
- 对feien进行模拟访问测试
http://192.168.68.152:9000/consumer-feign-passport/v1/auth/login?token=122222
for i in `seq 10000` ;do curl http://192.168.68.152:9000/consumer-feign-passport/passport?token=123123 ;echo "";done
{"msg":"后台服务passport-修改配置测试","api":"/passport","type":"feignPassport","status":200}
{"code":403,"msg":"服务限流, 请立刻停止非法访问"}
{"code":403,"msg":"服务限流, 请立刻停止非法访问"}
{"code":403,"msg":"服务限流, 请立刻停止非法访问"}
...
- 对restTemplate passport进行模拟访问测试
for i in `seq 10000` ;do curl http://192.168.68.152:9000/consumer-passport/v1/auth/login?token=122222 ;echo "";done
for i in `seq 10000` ;do curl http://192.168.68.152:9000/consumer-passport/passport?token=123123 ;echo "";done
{"msg":"demo passport restTemplate /v1/auth/login api","api":"{\"msg\":\"demo passport api\",\"api\":\"/v1/auth/consumer-passport\",\"type\":\"passportProvider\",\"status\":200}","type":"restTemplatePassport","status":200}
{"code":403,"msg":"服务限流, 请立刻停止非法访问"}
{"code":403,"msg":"服务限流, 请立刻停止非法访问"}
{"code":403,"msg":"服务限流, 请立刻停止非法访问"}
...
这里显示的内容是因为我们做了服务限流。
高并发系统中有三把利器用来保护系统:缓存、降级和限流。限流的目的是为了保护系统不被大量请求冲垮,通过限制请求的速度来保护系统。在电商的秒杀活动中,限流是必不可少的一个环节。
3.7 消费者调用
feign调用
restTemplate调用
3.7.1 什么是Feign
Feign是模板化的http客户端,可以帮助我们更快捷,优雅的调用http API(Rest)
Spring Cloud 对Feign进行了增强,使Feign支持Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便
3.7.2 为什么需要Feign
- 前面已经提到在消费后台服务的时候已经存下RestTemplate服务,为什么还需要Feign?
- Feign的目的是尽量的减少资源和代码来实现和HTTP API的连接(HTTP客户端封装)内网与外网调用。
3.7.3 什么是restTemplate
RestTemplate是Spring提供的额用于访问Rest服务的客户端,它提供了多种便捷访问远程http服务的方法,能够大大提高客户端的编写效率。
当后台服务,比如新闻资讯服务启动以后,用户需要访问,那么需要通过consumer访问,在本实例中consumer独立为一个服务,在实际的应用开发阿忠,会与网关集成为一个整体的服务。
3.7.4 Frign与restTemplate对比
代码框架实现反向代理+负载均衡
比较类型 | restTemplate+ribbon | Feign(自带ribbon) |
---|---|---|
可读性,可维护性 | 欠佳(无法从URL直观了解这个远程调用过程) | 极佳 |
开发体验 | 欠佳(拼接URL) | 极佳(代码整洁) |
风格一致性 | 一般(本地API调用和restTemplate调用的代码风格不同) | 极佳(完全一致,不点开feign的接口根本不会察觉这是一个远程调用而非本地api调用) |
性能 | 较好 | 中等(性能是restTemplate的50%左右,如果为feign配置连接池,性能可提升15%左右) |
灵活性 | 极佳 | 中等(内置功能能满足大多数项目的需求) |
3.8 网关调用过程
- 把用户需要请求的URL地址通过路由的方式转发到后台的服务,同时也实现鉴权的功能。
网关位置
3.8.1 网关调用restTemplate接口过程
- 负载均衡根据调度算法调度到网关系统
- 网关系统接收请求以后,如果消费者(restTemplate)返回正确,那么状态值为200,内容里面会包括provider返回的Json内容。
- 消费者接收请求以后,如果服务提供者(Provider)返回正确,那么状态值为200.
3.8.2 网关调用Feign接口过程
- 负载均衡根据调度算法调度到网关系统
- 网关系统接收请求以后,如果消费者(feign)返回正确,那么状态值为200,内容里面会包括provider返回的Json内容。
- 消费者接收请求以后,如果服务提供者(provider)返回正确,那么状态值为200.
调用过程于restTemplate相同,只是feign多封装了一层http client。
3.9 小结
- 所有服务注册到注册中心,并且每个服务可以展示多个实例
- 注册实例分为:临时实例与永久实例
- 网关:负责前台请求到后台的调用,起鉴权作用(配置文件路由/动态路由)
- Provider:后台真正的服务提供者
- Feign:网关通过此服务消费Provider
- restTemplate:网关通过此服务消费Provider
- 配置中心:在配置中心修改配置以后,可以实时通知到客户端,并且可以回滚配置到上一个版本。