当前位置: 首页>后端>正文

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking))

1、说明

在K8s Paas平台搭建SpringCloud微服务框架,进行微服务开发。网关采用Zuul1、服务注册与发现采用Eureka。链路跟踪与日志采集采用Skywalking。Skywalking日志采集是Skywalking8.5.0版本之后的功能,Skywalking日志采集采用服务工程主动推送的方式,与logback集成,可以满足中小型系统的日志采集和分析,数据库可选用elasticsearch,能保证良好的搜索性能。

新建一个k8s命名空间进行实验:

Yaml:

apiVersion: v1

kind: Namespace

metadata:

??? name: sclouds

??? labels:

?????? name: sclouds

设置默认命名空间:

kubectl config set-context $(kubectl config current-context) --namespace=sclouds

2、Eureka容器集群

2.1.StatefulSet、Headless Service

Eureka搭建容器集群,需要依赖k8s的statefulset组件。Eureka-server的每个实例需要相互同步状态。

StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括

稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现。

稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现。

有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),有序收缩,有序删除(即从N-1到0)。

使用StatefulSet,StatefulSet中每个Pod的DNS就是固定的,格式为

??? statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local

serviceName为Headless Service的名字0..N-1为Pod所在的序号,从0开始到N-1statefulSetName为StatefulSet的名字namespace为服务所在的namespace,Headless Service和StatefulSet必须在相同的namespacecluster.local为Cluster Domain

2.2.Ecureka Springboot镜像

集群由两个ecureka服务组成,服务工程基于Springboot开发,打包成jar包,最后打包成docker镜像在k8s上部署。

Sprinboot版本:2.6.2

SpringCloud版本:2021.0.1

pom.xml设置,引入spring-cloud-starter-netflix-eureka-server:

引入spring-boot-starter-web、spring-cloud-starter-netflix-eureka-server

? ? <dependencies>

? ? ? ? <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-server</artifactId>

? ? ? ? </dependency>

? ? ? ? <dependency>

? ? ? ? ? ? <groupId>org.springframework.boot</groupId>

? ? ? ? ? ? <artifactId>spring-boot-starter-test</artifactId>

? ? ? ? ? ? <scope>test</scope>

? ? ? ? </dependency>

? ? </dependencies>

? ? <dependencyManagement>

? ? ? ? <dependencies>

? ? ? ? ? ? <dependency>

? ? ? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>

? ? ? ? ? ? ? ? <artifactId>spring-cloud-dependencies</artifactId>

? ? ? ? ? ? ? ? <version>${spring-cloud.version}</version>

? ? ? ? ? ? ? ? <type>pom</type>

? ? ? ? ? ? ? ? <scope>import</scope>

? ? ? ? ? ? </dependency>

? ? ? ? </dependencies>

</dependencyManagement>

application.properties属性设置:

spring.application.name=register-server

server.port=8000

management.server.port=8001

eureka.instance.leaseRenewalIntervalInSeconds=10

eureka.instance.leaseExpirationDurationInSeconds=30

eureka.instance.hostname=${MY_POD_NAME}.register-server

eureka.instance.prefer-ip-address=true

eureka.client.fetch-registry=true

eureka.client.register-with-eureka=true

eureka.client.service-url.defaultZone=http://register-server-0.register-server:8000/eureka/,http://register-server-1.register-server:8000/eureka/

eureka.client.service-url.registryFetchIntervalSeconds=10

eureka.client.service-url.disable-delta=true

eureka.server.evictionIntervalTimerInMs=4000

eureka.server.enable-self-preservation=false

Dockfile:

FROM java:8

VOLUME /tmp

ADD eurekaclu-0.0.1-SNAPSHOT.jar /eurekaclu-0.0.1-SNAPSHOT.jar

ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/eurekaclu-0.0.1-SNAPSHOT.jar"]

2.3.k8s service服务暴露

使用2.2的镜像部署statefulset。Service关联暴露服务。为了方便访问,设置成nodePort型,暴露外网端口。

statefulset:

apiVersion: apps/v1

kind: StatefulSet

metadata:

? name: register-server

? labels:

? ? service: register-server

spec:

? replicas: 2

? serviceName: register-server

? selector:

? ? matchLabels:

? ? ? service: register-server

? template:

? ? metadata:

? ? ? labels:

? ? ? ? service: register-server

? ? ? annotations:

? ? ? ? service: register-server

? ? spec:

? ? ?s:

? ? ? ? - name: register-server

? ? ? ? ? image: dw/eurekaclu-2

? ? ? ? ? imagePullPolicy: IfNotPresent

? ? ? ? ? env:

? ? ? ? ? - name: MY_POD_NAME

? ? ? ? ? ? valueFrom:

? ? ? ? ? ? ? fieldRef:

? ? ? ? ? ? ? ? fieldPath: metadata.name

? ? ? ? ? ports:

? ? ? ? ? ? - name: http

? ? ? ? ? ? ?Port: 8000

? ? ? ? ? ? ? protocol: TCP

? ? ? ? ? readinessProbe:

? ? ? ? ? ? httpGet:

? ? ? ? ? ? ? path: /actuator/health

? ? ? ? ? ? ? port: 8001

? ? ? ? ? ? ? scheme: HTTP

? ? ? ? ? ? failureThreshold: 3

? ? ? ? ? ? initialDelaySeconds: 60

? ? ? ? ? ? periodSeconds: 10

? ? ? ? ? ? successThreshold: 1

? ? ? ? ? ? timeoutSeconds: 10

? ? ? ? ? resources:

? ? ? ? ? ? limits:

? ? ? ? ? ? ? # cpu: 100m

? ? ? ? ? ? ? memory: 1Gi

? ? ? ? ? ? requests:

? ? ? ? ? ? ? ? # cpu: 100m

? ? ? ? ? ? ? memory: 1Gi

? ? ? ? ? volumeMounts:

? ? ? ? ? - mountPath: /Charts

? ? ? ? ? ? name: data

? ? ? volumes:

? ? ? - name: data

? podManagementPolicy: "Parallel"

Service:

apiVersion: v1

kind: Service

metadata:

? name: register-server

? labels:

? ? service: register-server

spec:

? type: NodePort

? ports:

? ? - port: 8000

? ? ? targetPort: 8000

? ? ? protocol: TCP

? ? ? name: http

? ? ? nodePort: 30111

? selector:

? ? service: register-server

依次应用statefulset、service,部署两个statefulset:

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking)),第1张
ecureka satefulset

这样可以得到两个ecurka-server的集群内url,和2.2节的属性设置对应:

register-server-0.register-server:8000

register-server-1.register-server:8000

导出nodePort,浏览器登录验证:

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking)),第2张
注册中心


3.Zuul1容器集群

Zuul1是springcloud早期的服务网关,这里使用旧一点的稳定版本。

3.1.zuul1 springboot

Zuul也要注册到eureka,需要引入eureka-client和netflix-zuul。服务注册ecureka使用上一章搭建的集群,根据k8s服务url规则,ecureka服务的url为http://register-server.sclouds.svc.cluster.local:8000/eureka/,k8s服务进行负载分发到两个stateful实例

Springboot版本:2.1.8

SpringCloud版本:Greenwich.SR2

Pom.xml:

<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-netflix-zuul</artifactId>

</dependency>

application.properties:

server.port=7005

spring.application.name=springboot-zuul-server

eureka.client.serviceUrl.defaultZone=http://register-server.sclouds.svc.cluster.local:8000/eureka/

zuul.stripPrefix=false

zuul.ignored-services="*"

zuul.routes.api-a.path=/ribbon/**

zuul.routes.api-a.serviceId=springboot-eureka-client

zuul.routes.api-a.strip-prefix=false

ribbon.eureka.enabled=true

eureka.instance.prefer-ip-address=true

注:这里设置一个路由规则,路由到springboot-eureka-client微服务(下文有例子)

Dockerfile:

FROM java:8

VOLUME /tmp

ADD ecurkazuul-0.0.1-SNAPSHOT.jar /ecurkazuul-0.0.1-SNAPSHOT.jar

ADD skagent /skagent

ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/ecurkazuul-0.0.1-SNAPSHOT.jar"]

3.2.k8s service

Zuul集群实例不需要互相同步状态,部署Deployment即可。Service进行服务暴露负载

Yaml:

apiVersion: v1

kind: Service

metadata:

? name: ecurka-zuul

? namespace: sclouds

? labels:

? ? verison: "1.0.0"

? ? env: "test"

spec:

? type: NodePort

? selector:

? ? app: ecurka-zuul

? ? release: master

? ports:

? ? ? - name: http

? ? ? ? port: 7005

? ? ? ? targetPort: 7005

? ? ? ? nodePort: 30112

---

apiVersion: apps/v1

kind: Deployment

metadata:

? name: ecurka-zuul

? namespace: sclouds

? labels:

? ? verison: "1.0.0"

? ? env: "test"

spec:

? replicas: 2

? selector:

? ? matchLabels:

? ? ? app: ecurka-zuul

? ? ? release: master

? template:

? ? metadata:

? ? ? labels:

? ? ? ? app: ecurka-zuul

? ? ? ? release: master

? ? spec:

? ? ?s:

? ? ? ? - name: ecurka-zuul

? ? ? ? ? image: dw/ecurka-zuul

? ? ? ? ? imagePullPolicy: IfNotPresent

? ? ? ? ? ports:

? ? ? ? ? ? - name: http

? ? ? ? ? ? ?Port: 7005

应用service,部署两个pod实例:

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking)),第3张
pods

登录ecureka,看到有两个zuul服务实例在运行:

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking)),第4张
ecureka

4、SkyWalking

这里简单介绍一下Windows单机部署

4.1.软件版本

Skywalking 8.7.0

下载地址:https://skywalking.apache.org/downloads/

Elasticsearch 6.8.23

下载地址:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-8-23

本文选择Elasticsearch 作为skywalking的数据库,skywalking与el的版本需要对应,如果使用Elasticsearch7,需要下载es后缀的skywalking版本。

4.2.elasticsearch

elasticsearch.yml修改:

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking)),第5张

4.3.Skywalking

分为两个服务,后台信息收集服务oap,前端门户ui(skywalking-webapp)

?OAP后台服务

config:application.yml

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking)),第6张
选择数据库类型

?UI门户工程

webapp.yml,如果端口被占用,可修改默认端口

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking)),第7张
webapp.yml


4.4.服务启动

启动Elasticsearch

执行elasticsearch.bat,默认占用9200端口

启动skywalking

执行startup.bat,或者分别执行oapService.bat、webappService.bat,默认占用11800,12800,8080端口。

4.5.Springboot工程接入

Skywalking对于Java工程是非侵入的,通过探针进行接口探测,数据上报。只需要在启动后台服务时,加入启动参数,指定Skywalking agent依赖包以及oap服务Url,idea中可在工程启动配置中配置,有两个属性需要注意,skywalking.agent.service_name是skywalking中显示的服务名称,不同服务需要区分。skywalking.collector.backend_service,是skywalking服务端的地址,要根据实际情况修改。本文中,skywalking没有部署到k8s中,写的是skywalking部署主机的地址。

参考:

-javaagent:J:\tmppro\demo\skagent\skywalking-agent.jar -Dskywalking.agent.service_name=DemoHelloService -Dskywalking.collector.backend_service=192.168.76.54:11800

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking)),第8张
idea java vm参数

HTTP调用,Skywalking前端观测

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking)),第9张
skywalking


4.6.springboot服务docker镜像打包修改

拷贝skywalking agent依赖到docker镜像打包目录

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking)),第10张
docker打包目录

修改Dockerfile,加入加粗字体部分:

FROM java:8

VOLUME /tmp

ADD ecurkaclient-0.0.1-SNAPSHOT.jar /ecurkaclient-0.0.1-SNAPSHOT.jar

ADD skagent /skagent

ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-javaagent:/skagent/skywalking-agent.jar","-Dskywalking.agent.service_name=EurekaClient","-Dskywalking.collector.backend_service=192.168.76.54:11800","-jar","/ecurkaclient-0.0.1-SNAPSHOT.jar"]

5、服务实例


5.1.springboot镜像

Java代码,设置两个url作为服务实验:

package com.example.ecurkaclient;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.RestController;

@RestController

public class TestController {

? ? private static final Logger log = LoggerFactory.getLogger(TestController.class);

? ? @RequestMapping(value = "/hello", method = RequestMethod.GET)

? ? public ResponseX testHello() {

? ? ? ? ResponseX x = new ResponseX();

? ? ? ? x.setMsg("hello-x");

? ? ? ? log.info("######################################\n" + "hello");

? ? ? ? return x;

? ? }

? ? @RequestMapping(value = "/helloworld", method = RequestMethod.GET)

? ? public ResponseX testHellox() {

? ? ? ? ResponseX x = new ResponseX();

? ? ? ? x.setMsg("hello-world-x");

? ? ? ? log.info("######################################\n" + "hello-world");

? ? ? ? return x;

? ? }

}

application.properties:

server.port=7004

spring.application.name=springboot-eureka-client

eureka.client.serviceUrl.defaultZone=http://register-server.sclouds.svc.cluster.local:8000/eureka/

eureka.instance.prefer-ip-address=true

注:spring.application.name和前面zuul网关设置的zuul.routes.api-a.serviceId要对应。Zuul网关根据服务名称进行路由。

Dockerfile打包镜像:

FROM java:8

VOLUME /tmp

ADD ecurkaclient-0.0.1-SNAPSHOT.jar /ecurkaclient-0.0.1-SNAPSHOT.jar

ADD skagent /skagent

ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-javaagent:/skagent/skywalking-agent.jar","-Dskywalking.agent.service_name=EurekaClient","-Dskywalking.collector.backend_service=192.168.76.54:11800","-jar","/ecurkaclient-0.0.1-SNAPSHOT.jar"]

5.2.k8s service

Yaml:

apiVersion: v1

kind: Service

metadata:

? name: ecurka-client

? namespace: sclouds

? labels:

? ? verison: "1.0.0"

? ? env: "test"

spec:

? selector:

? ? app: ecurka-client

? ? release: master

? ports:

? ? ? - name: http

? ? ? ? port: 7004

? ? ? ? targetPort: 7004

---

apiVersion: apps/v1

kind: Deployment

metadata:

? name: ecurka-client

? namespace: sclouds

? labels:

? ? verison: "1.0.0"

? ? env: "test"

spec:

? replicas: 2

? selector:

? ? matchLabels:

? ? ? app: ecurka-client

? ? ? release: master

? template:

? ? metadata:

? ? ? labels:

? ? ? ? app: ecurka-client

? ? ? ? release: master

? ? spec:

? ? ?s:

? ? ? ? - name: ecurka-client

? ? ? ? ? image: dw/ecurka-client

? ? ? ? ? imagePullPolicy: IfNotPresent

? ? ? ? ? ports:

? ? ? ? ? ? - name: http

? ? ? ? ? ? ?Port: 7004

6、日志采集(SkyWalking)

logback设置GRPCLogClientAppender,设置日志级别:

<?xml version="1.0" encoding="UTF-8"?>

<configuration>

? ? <appender name="msystem-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">

? ? ? ? <!-- 日志输出编码 -->

? ? ? ? <encoder>

? ? ? ? ? ? <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->

? ? ? ? ? ? <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>

? ? ? ? </encoder>

? ? </appender>

? ? <root level="info">

? ? ? ? <appender-ref ref="msystem-log"/>

? ? </root>

</configuration>

完成上述配置,日志就会上传到skywalking

log.info("######################################\n" + "hello-world");

SpringCloud微服务实例(K8S、Eureka、Zuul、Skywalking)),第11张
skywalking日志界面

https://www.xamrdz.com/backend/3hr1923516.html

相关文章: