我的那些年(13)~主推微服务架构
我的那些年(13)~主推微服务架构
- 整个系统走向微服务架构
- 网关
- 服务注册与发现
- 配置中心
- 熔断器
- 链路跟踪
- 授权与鉴权
- 服务间的通讯-同步feign
- 服务间的通讯-异步消息
- 日志收集
个系统走向微服务架构
公司系统比较多,耦合度比较大,将这些模块进行拆分,各个负责自己的模块,减少相互之间的直接依赖,版本迭代互不影响,做到最小粒度的部署,这就是微服务,也是未来软件架构与设计的一个趋势!
典型的微服务架构图 典型的微服务架构图
服务间的调用
网关
网关作为整个系统的门面存在,当然一个超级大系统可能出现多个网关,而把关系比较紧密的系统通过一个网关对外提供服务,这是一种比较好的作法,对前端和用户来说,它还是一个系统,而对于后端来说,它是由多个子服务组成,我们选择的网关产品是比较流行的zuul,而springcloud2.0出来后,也推出了新的gateway组件,当然无论是使用哪个网关产品,功能都是相同的!
网关主要起到了路由,请求过滤,统一授权,限流等功能
zuul.routes.userinfo.path=/getuser/** zuul.routes.userinfo.serviceid=userinfo-consumer zuul.ratelimit.enabled=true zuul.ratelimit.policies.userinfo.limit=3 zuul.ratelimit.policies.userinfo.refresh-interval=60 zuul.ratelimit.policies.userinfo.type=origin # 测试客户端如果60s内请求超过三次,服务端就抛出异常,一分钟后又可以正常请求 # 某个ip的客户端被限流并不影响其他客户端,即api网关对每个客户端限流是相互独立的
服务注册与发现
让多个子服务进行通讯,要求这些服务在一个网络里,它们之间是可以互通的,而当服务越来越多,每个服务的端口,ip地址也会越来越繁琐,而这时服务注册组件就派上用场了,它将服务的ip和端口与一个服务名称进行映射,让开发人员只关注名称,application.name
即可,而名称与真实服务的链路过程由服务注册组件实现,我们在选择服务注册组件时,选择了eureka。
eureka服务端
server: port: ${port:8761} management: port: ${bg_port:8762} application: name: ${name:eurekaserver} spring: profiles: active: dev --- eureka: profile: dev instance: hostname: ${application.name} perferipaddress: true #基于ip地址注册 client: registerwitheureka: false #false表示不向注册中心注册自己。 fetchregistry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务 serviceurl: defaultzone: ${url:http://${eureka.instance.hostname}:${server.port}/eureka/}
eureka客户端注册到服务端
spring: application: name: gateway profiles: active: ${spring_profiles_active:dev} server: port: 8003 eureka: client: service-url: defaultzone: http://${eureka.host:localhost}:${eureka.port:6761}/eureka/, http://${eureka.host:localhost}:${eureka.port:5761}/eureka/
配置中心
将所有服务的配置都集中管理,这是一个不错的想法,当配置更新后,不需要启动服务,而通过消息广播的方法通讯服务即可,这就是配置中心的作用。之前的单体应用时,每个应用都有自己的配置文件,而当项目多了之后,这些配置文件不容易管理,要修改其中一些配置时,需要分别进入对应的服务里,而且这些配置也无法实现继承,重复的代码很多,比如很多服务都用了rabbitmq,redis等,单体应用里,你需要复制这些配置到每个服务里,而有了配置中心,你只需要在application.yml
里进行公用配置即可,而其它服务的配置会自动继承。
配置中心使用了加密算法保存了配置文件中的敏感信息
server.port: ${port:8888} management.port: ${bg_port:8889} spring: application.name: lind-configserver profiles.active: development encrypt: key-store: location: file:///users/lind.zhang/github/dockerdeploy/swarm/server.jks password: changeit alias: config-server-key secret: changeit --- spring: profiles: svt cloud: config: server: git: uri: /config_repo --- spring: profiles: development cloud: config: server: git: uri: /config_repo
对配置进行加密码
要配置非对称密钥,您可以将密钥设置为pem编码的文本值(encrypt.key),也可以通过密钥库设置密钥(例如由jdk附带的keytool实用程序创建)。密钥库属性为encrypt.keystore.*,*等于
- location(a resource位置),
- password(解锁密钥库)
- alias(以识别商店中使用的密钥)。
使用公钥进行加密,需要私钥进行解密。因此,原则上您只能在服务器中配置公钥,如果您只想进行加密(并准备使用私钥本地解密值)。实际上,您可能不想这样做,因为它围绕所有客户端传播密钥管理流程,而不是将其集中在服务器中。另一方面,如果您的配置服务器真的相对不安全,并且只有少数客户端需要加密的属性,这是一个有用的选项。
创建用于测试的密钥库
要创建一个密钥库进行测试,您可以执行以下操作:
$ keytool -genkeypair -alias mytestkey -keyalg rsa \ -dname "cn=web server,ou=unit,o=organization,l=city,s=state,c=us" \ -keypass changeme -keystore server.jks -storepass letmein
将server.jks文件放在类路径(例如)中,然后在您的application.yml中配置服务器:
encrypt: keystore: location: classpath:/server.jks password: letmein alias: mytestkey secret: changeme
使用端的yml文件
foo: bar: `{cipher}{key:testkey}...`
熔断器
熔断在微服务中表现非常突出,在多个服务进行并行式调用时,这个熔断功能就显得非常重要了,比如a调用b,a再调用c,a再调用d,而在这个并行调用过程中,当b出现问题时,后面的c,d将不会执行,而默认情况下a会等到b达到超时后才会做出响应,而影响a调用其它服务,从而导致a这个接口整体变慢;而有了熔断之后,当请求b接口出现问题时,你可以有很多能策略,如重试机制,快速返回等。
hystrix的基本配置,主要是对请求超时时间的配置
hystrix: command: default: execution: timeout: enabled: true isolation: strategy: semaphore #hystrix策略为thread时,threadlocal为空 thread: #目前有两个容器实例,单个请求超时5s,+重试>10s,超15s则熔断 timeoutinmilliseconds: 15000
链路跟踪
当一个服务a调用服务b时,服务b也可能会调用服务c,这就形成了一个链表,在响应时的顺序是相反的,所以这是一个双向的链表,在这个链表里,我们希望对它进行跟踪,因为在一个请求出现问题时,你很难找到问题出现在哪个环节,所以我们的请求需要有一个traceid在各个服务链表间进行传递,这就是链路跟踪的原理。
下面是链路跟踪组件sleuth和日志收集分析工具zipkin的配置
spring: application: name: user sleuth: web: client: enabled: true sampler: probability: 1.0 # 将采样比例设置为 1.0,也就是全部都需要。默认是 0.1 zipkin: base-url: http://localhost:9411/ # 指定了 zipkin 服务器的地址
下次有时间再说一下剩下的内容
- 授权与鉴权
- 服务间的通讯-同步feign
- 服务间的通讯-异步消息
- 日志收集
上一篇: Python-14-常用模块
下一篇: zuul 动态网关路由