Spring Cloud 与 K8s 的微服务设计

Spring Boot 1.x 与 2.x 的区别

在《 微服务 Spring Cloud 架构设计 》一文中,笔者讲过 Spring Cloud 的架构设计。其实 Spring Boot 在一开始时,运用到的基本就是 Eureka、Config、Zuul、Ribbon、Feign、Hystrix 等。到了 Spring Boot 2.x 的时候,大量的组件开始风云崛起。下面简单列下这两个版本之间的区别如下。

Spring Boot 1.x 中,session 的超时时间是这样的:

server.session.timeout=3600

复制代码

而在 2.x 中:

server.servlet.session.timeout=PT120M

复制代码

截然不同的写法,cookie 也是一样的:

server:  servlet:    session:      timeout: PT120M      cookie:        name: ORDER-SERVICE-SESSIONID

复制代码

  • 应用的 ContextPath 配置属性改动,跟上面的 session 一样,加上了一个 servlet。

  • Spring Boot 2.x 基于 Spring 5,而 Spring Boot 1.x 基于 Spring 4 或较低。

  • 统一错误处理的基类 AbstarctErrorController 的改动。

  • 配置文件的中文可以直接读取,不需要转码。

  • Acutator 变化很大,默认情况不再启用所有监控,需要定制化编写监控信息,完全需要重写,HealthIndicator,EndPoint 同理。

  • 从 Spring Boot 2.x 开始,可以与 K8s 结合来实现服务的配置管理、负载均衡等,这是与 1.x 所不同的。

K8s 的一些资源的介绍

上面说到 Spring Boot 2.x 可以结合 K8s 来作为微服务的架构设计,那么就先来说下 K8s 的一些组件吧。

ConfigMap,看到这个名字可以理解:它是用于保存配置信息的键值对,可以用来保存单个属性,也可以保存配置文件。对于一些非敏感的信息,比如应用的配置信息,则可以使用 ConfigMap。

创建一个 ConfigMap 有多种方式如下。

1. key-value 字符串创建

kubectl create configmap test-config --from-literal=baseDir=/usr

复制代码

上面的命令创建了一个名为 test-config,拥有一条 key 为 baseDir,value 为 "/usr" 的键值对数据。

2. 根据 yml 描述文件创建

apiVersion: v1kind: ConfigMapmetadata:  name: test-configdata:  baseDir: /usr

复制代码

也可以这样,创建一个 yml 文件,选择不同的环境配置不同的信息:

kind: ConfigMapapiVersion: v1metadata:  name: cas-serverdata:  application.yaml: |-    greeting:      message: Say Hello to the World    ---    spring:      profiles: dev    greeting:      message: Say Hello to the Dev    spring:      profiles: test    greeting:      message: Say Hello to the Test    spring:      profiles: prod    greeting:      message: Say Hello to the Prod

复制代码

注意点:

  1. ConfigMap 必须在 Pod 使用其之前创建。

  2. Pod 只能使用同一个命名空间的 ConfigMap。

当然,还有其他更多用途,具体可以参考官网。

Service,顾名思义是一个服务,什么样的服务呢?它是定义了一个服务的多种 pod 的逻辑合集以及一种访问 pod 的策略。

service 的类型有四种:

  • ExternalName:创建一个 DNS 别名指向 service name,这样可以防止 service name 发生变化,但需要配合 DNS 插件使用。

  • ClusterIP:默认的类型,用于为集群内 Pod 访问时,提供的固定访问地址,默认是自动分配地址,可使用 ClusterIP 关键字指定固定 IP。

  • NodePort:基于 ClusterIp,用于为集群外部访问 Service 后面 Pod 提供访问接入端口。

  • LoadBalancer:它是基于 NodePort。

如何使用 K8s 来实现服务注册与发现

从上面讲的 Service,我们可以看到一种场景:所有的微服务在一个局域网内,或者说在一个 K8s 集群下,那么可以通过 Service 用于集群内 Pod 的访问,这就是 Service 默认的一种类型 ClusterIP,ClusterIP 这种的默认会自动分配地址。

那么问题来了,既然可以通过上面的 ClusterIp 来实现集群内部的服务访问,那么如何注册服务呢?其实 K8s 并没有引入任何的注册中心,使用的就是 K8s 的 kube-dns 组件。然后 K8s 将 Service 的名称当做域名注册到 kube-dns 中,通过 Service 的名称就可以访问其提供的服务。那么问题又来了,如果一个服务的 pod 对应有多个,那么如何实现 LB?其实,最终通过 kube-proxy,实现负载均衡。

说到这,我们来看下 Service 的服务发现与负载均衡的策略,Service 负载分发策略有两种:

  • RoundRobin:轮询模式,即轮询将请求转发到后端的各个 pod 上,其为默认模式。

  • SessionAffinity:基于客户端 IP 地址进行会话保持的模式,类似 IP Hash 的方式,来实现服务的负载均衡。

其实,K8s 利用其 Service 实现服务的发现,其实说白了,就是通过域名进行层层解析,最后解析到容器内部的 ip 和 port 来找到对应的服务,以完成请求。

下面写一个很简单的例子:

apiVersion: v1kind: Servicemetadata:  name: cas-server-service  namespace: defaultspec:  ports:  - name: cas-server01    port: 2000    targetPort: cas-server01  selector:    app: cas-server

复制代码

可以看到执行 kubectl apply -f service.yaml 后:

root@ubuntu:~$ kubectl get svcNAME                          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)              AGEadmin-web-service             ClusterIP   10.16.129.24    <none>        2001/TCP              84dcas-server-service            ClusterIP   10.16.230.167   <none>        2000/TCP               67dcloud-admin-service-service   ClusterIP   10.16.25.178    <none>        1001/TCP         190d

复制代码

这样,我们可以看到默认的类型是 ClusterIP,用于为集群内 Pod 访问时,可以先通过域名来解析到多个服务地址信息,然后再通过 LB 策略来选择其中一个作为请求的对象。

K8s 如何来处理微服务中常用的配置

在上面,我们讲过了几种创建 ConfigMap 的方式,其中有一种在 Java 中常常用到:通过创建 yml 文件来实现配置管理。

比如:

kind: ConfigMapapiVersion: v1metadata:  name: cas-serverdata:  application.yaml: |-    greeting:      message: Say Hello to the World    ---    spring:      profiles: dev    greeting:      message: Say Hello to the Dev    spring:      profiles: test    greeting:      message: Say Hello to the Test    spring:      profiles: prod    greeting:      message: Say Hello to the Prod

复制代码

上面创建了一个 yml 文件,同时,通过 spring.profiles 指定了开发、测试、生产等每种环境的配置。

具体代码:

apiVersion: apps/v1kind: Deploymentmetadata:  name: cas-server-deployment  labels:    app: cas-serverspec:  replicas: 1  selector:    matchLabels:      app: cas-server  template:    metadata:      labels:        app: cas-server    spec:      nodeSelector:        cas-server: "true"      containers:      - name: cas-server        image: {
  { cluster_cfg['cluster']['docker-registry']['prefix'] }}cas-server        imagePullPolicy: Always        ports:          - name: cas-server01            containerPort: 2000        volumeMounts:        - mountPath: /home/cas-server          name: cas-server-path        args: ["sh", "-c", "nohup java $JAVA_OPTS -jar -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC cas-server.jar --spring.profiles.active=dev", "&"]      hostAliases:      - ip: "127.0.0.1"        hostnames:        - "gemantic.localhost"      - ip: "0.0.0.0"        hostnames:        - "gemantic.all"      volumes:<
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值