docker+k8s+istio项目实例

编程入门 行业动态 更新时间:2024-10-11 11:16:47

docker+k8s+istio项目<a href=https://www.elefans.com/category/jswz/34/1771375.html style=实例"/>

docker+k8s+istio项目实例

0.本博客目标■■■■■■■■■■■■■■■■

最近学习k8s+istio项目知识,本博客只是想把项目学习经验分享给大家,以便大家少走弯路。

k8s,isito的知识点众多,内容体系庞杂,本博客只做简单验证,能够让你快速搭建起运行环境,并且快速搭建项目验证k8s及istio。

1.运行环境■■■■■■■■■■■■■■■■

Linux centos7.6

Docker 18.09.0

kubernetes 1.14.0-0

istio-1.4.10

运行的业务项目为Java项目,JDK1.8

2.环境安装■■■■■■■■■■■■■■■■

★2.0.更新yum源(3个节点都安装)■■■■■■

yum -y update
yum install -y conntrack ipvsadm ipset jq sysstat curl iptables libseccomp

★2.1.docker安装(3个几点都安装)■■■■■■

yum install -y docker-ce-18.09.0 docker-ce-cli-18.09.0 containerd.io

       设置开机启动

sudo systemctl start docker && sudo systemctl enable docker

★2.2.kubernetes安装■■■■■■

        我这里k8s集群安装1主2从安装。

       ●修改hosts文件■■■■

         主节点:设置master的hostname,并且修改hosts文件

sudo hostnamectl set-hostname mvi /etc/hosts
192.168.42.130 m
192.168.42.131 w1
192.168.42.132 w2

         2个从节点:设置worker01/02的hostname,并且修改hosts文件

sudo hostnamectl set-hostname w1
sudo hostnamectl set-hostname w2vi /etc/hosts
192.168.42.130 m
192.168.42.131 w1
192.168.42.132 w2

         设置完后,互相ping一下(ping m/ping w1/ping w2),确认设置没有问题。

       ●系统基础前提配置(3个节点都安装)■■■■

         ▲1.关闭防火墙■■

systemctl stop firewalld && systemctl disable firewalld

         ▲2.关闭selinux■■

setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

         ▲3.关闭swap■■

swapoff -a
sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab

         ▲4.配置iptables的ACCEPT规则■■

iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat && iptables -P FORWARD ACCEPT

         ▲5.设置系统参数■■

cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOFsysctl --system

       ●安装 kubeadm,kubelet 和 kubectl(3个节点都安装)■■■■

         ▲1.配置yum源■■

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=kubernetes
baseurl=
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=.gpg.gpg
EOF

         ▲2.安装kubeadm,kubelet 和 kubectl■■

yum -y install kubernetes-cni = 0.7.5
yum install -y kubeadm-1.14.0-0 kubelet-1.14.0-0 kubectl-1.14.0-0yum -y remove kubelet
yum install -y kubelet-1.14.0-0
yum install -y kubeadm-1.14.0-0

         ▲3.docker和k8s设置同一个cgroup■■

            docker

vi /etc/docker/daemon.jsonexec-opts:["native.cgroupdriver-systemd"],systemctl restart docker

            kubelet

sed -i "s/cgroup-driver=systemd/cgroup-driver=cgroupfs/g" /etc/systemd/system/kubelet.service.d/10-kubeadm.confsystemctl enable kubelet && systemctl start kubelet

         安装k8s时需要使用一些国外镜像。由于这些镜像不能直接访问,所以需要特殊处理一下。

          ▲4.下载国外镜像方法■■

            需要先注册一个dockerhub的账号,然后通过dockerhub中转一下获取国外的镜像。dockerhub国内是可以访问到的,不过速度有点慢,需要忍耐一下。dockerhub地址:/

              打开网址:/

              随便点开一个课程,进入该课程,可以看到一个终端,如图所示:

 之后在该终端执行以下操作:

# 登录dockerhub,我的用户名是ryuu
docker login# 由于kacacoda是国外网站,所以可以直接在它的终端上拉取gcr镜像
docker pull docker.io/istio/kubectl:1.4.10# 给镜像改名,一定要是: 你的dockerhub用户名/镜像名:版本,否则无法推送到自己的镜像仓库
docker tag docker.io/istio/kubectl:1.4.10 ryuu/istio-kubectl:1.4.10# 推送到自己的dockerhub镜像仓库
docker push ryuu/istio-kubectl:1.4.10

这样就把国外的镜像拉取到了dockerhub镜像仓库中,然后在从dockerhub中拉取到本地,然后再打tag为原来的镜像名称,就完成了国外镜像的获取。

※需要下载的镜像

k8s.gcr.io/kube-apiserver:v1.14.0
k8s.gcr.io/kube-controller-manager:v1.14.0
k8s.gcr.io/kube-scheduler:v1.14.0
k8s.gcr.io/kube-proxy:v1.14.0
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.3.10
k8s.gcr.io/coredns:1.3.1

          ▲5.初始化主节点(在master上安装 ip:192.168.42.130)■■

kubeadm init --kubernetes-version=1.14.0 --apiserver-advertise-address=192.168.42.130 --pod-network-cidr=10.244.0.0/16

安装完成后获取日志中以下部分内容

  mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/configkubeadm join 192.168.42.130:6443 --token z3qetd.qzp04u03bvq9eeos \--discovery-token-ca-cert-hash sha256:0e7980b860a4ef29281469966f50b60dd8dbb608c2fdb3a971df81968aafb5ee

上面3行的命令需要在主节点上执行一遍。后面2行的内容在2个从节点上执行,用于将从节点加入集群。

          ▲6.安装网络插件calico(在主节点操作)■■

          需要事先下载以下镜像

calico/pod2daemon-flexvol:v3.9.1
calico/kube-controllers:v3.9.1
calico/cni:v3.9.1
kubectl apply -f .9/manifests/calico.yaml

           确认calico安装成功(可以看到calico的pod被启动起来即表示安装成功)

kubectl get pods --all-namespaces -w

          ▲7.将2个从节点加入集群■■

kubeadm join 192.168.42.130:6443 --token z3qetd.qzp04u03bvq9eeos \--discovery-token-ca-cert-hash sha256:0e7980b860a4ef29281469966f50b60dd8dbb608c2fdb3a971df81968aafb5ee 

           确认从节点加入成功,在主节点上操作

kubectl get nodes

          看到2个从节点即表示成功。

          ▲8.安装Ingress■■

             需要事先下载镜像

quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1

             给node打标签(用于指定ingress安装的node)

kubectl label nodes w1 name=ingress

              安装ingress

kubectl apply -f mandatory.yaml

对应的脚本文件mandatory.yaml

apiVersion: v1
kind: Namespace
metadata:name: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---kind: ConfigMap
apiVersion: v1
metadata:name: nginx-configurationnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---
kind: ConfigMap
apiVersion: v1
metadata:name: tcp-servicesnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---
kind: ConfigMap
apiVersion: v1
metadata:name: udp-servicesnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---
apiVersion: v1
kind: ServiceAccount
metadata:name: nginx-ingress-serviceaccountnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:name: nginx-ingress-clusterrolelabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx
rules:- apiGroups:- ""resources:- configmaps- endpoints- nodes- pods- secretsverbs:- list- watch- apiGroups:- ""resources:- nodesverbs:- get- apiGroups:- ""resources:- servicesverbs:- get- list- watch- apiGroups:- ""resources:- eventsverbs:- create- patch- apiGroups:- "extensions"- "networking.k8s.io"resources:- ingressesverbs:- get- list- watch- apiGroups:- "extensions"- "networking.k8s.io"resources:- ingresses/statusverbs:- update---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:name: nginx-ingress-rolenamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx
rules:- apiGroups:- ""resources:- configmaps- pods- secrets- namespacesverbs:- get- apiGroups:- ""resources:- configmapsresourceNames:# Defaults to "<election-id>-<ingress-class>"# Here: "<ingress-controller-leader>-<nginx>"# This has to be adapted if you change either parameter# when launching the nginx-ingress-controller.- "ingress-controller-leader-nginx"verbs:- get- update- apiGroups:- ""resources:- configmapsverbs:- create- apiGroups:- ""resources:- endpointsverbs:- get---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:name: nginx-ingress-role-nisa-bindingnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx
roleRef:apiGroup: rbac.authorization.k8s.iokind: Rolename: nginx-ingress-role
subjects:- kind: ServiceAccountname: nginx-ingress-serviceaccountnamespace: ingress-nginx---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:name: nginx-ingress-clusterrole-nisa-bindinglabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: nginx-ingress-clusterrole
subjects:- kind: ServiceAccountname: nginx-ingress-serviceaccountnamespace: ingress-nginx---apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-ingress-controllernamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx
spec:replicas: 1selector:matchLabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxtemplate:metadata:labels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxannotations:prometheus.io/port: "10254"prometheus.io/scrape: "true"spec:# wait up to five minutes for the drain of connectionsterminationGracePeriodSeconds: 300serviceAccountName: nginx-ingress-serviceaccounthostNetwork: truenodeSelector:name: ingresskubernetes.io/os: linuxcontainers:- name: nginx-ingress-controllerimage: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1args:- /nginx-ingress-controller- --configmap=$(POD_NAMESPACE)/nginx-configuration- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services- --udp-services-configmap=$(POD_NAMESPACE)/udp-services- --publish-service=$(POD_NAMESPACE)/ingress-nginx- --annotations-prefix=nginx.ingress.kubernetes.iosecurityContext:allowPrivilegeEscalation: truecapabilities:drop:- ALLadd:- NET_BIND_SERVICE# www-data -> 33runAsUser: 33env:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespaceports:- name: httpcontainerPort: 80- name: httpscontainerPort: 443livenessProbe:failureThreshold: 3httpGet:path: /healthzport: 10254scheme: HTTPinitialDelaySeconds: 10periodSeconds: 10successThreshold: 1timeoutSeconds: 10readinessProbe:failureThreshold: 3httpGet:path: /healthzport: 10254scheme: HTTPperiodSeconds: 10successThreshold: 1timeoutSeconds: 10lifecycle:preStop:exec:command:- /wait-shutdown---

    至此k8s集群搭建完成。

★2.3.istio安装■■■■■■

       ●1.下载压缩包,并解压(istio-1.4.10-linux.tar.gz)■■■■

       ●2.解压压缩包后配置环境变量■■■■

vi /etc/profile
export ISTIO_HOME=/opt/istio/istio-1.4.10
export PATH=$PATH:$ISTIO_HOME/binsource /etc/profile

       ●3.安装isito■■■■

需要事先下载以下镜像

docker.io/istio/kubectl:1.4.10
docker.io/istio/galley:1.4.10
grafana/grafana:6.4.3
quay.io/kiali/kiali:v1.15
docker.io/istio/mixer:1.4.10
docker.io/istio/proxyv2:1.4.10
docker.io/istio/pilot:1.4.10
docker.io/prom/prometheus:v2.12.0
docker.io/istio/citadel:1.4.10
docker.io/istio/sidecar_injector:1.4.10
docker.io/jaegertracing/all-in-one:1.14
cd /opt/istio/istio-1.4.10/install/kubernetes
kubectl apply -f istio-demo.yaml

查看istio对应的pod正常启动,确认istio安装正常

kubectl get pods -n istio-system

3.示例项目■■■■■■■■■■■■■■■■

示例羡慕整合了数据库(PostgreSQL)和分布式事务中间件(Seata)。本项目访问外部服务采用直接访问的方式,istio天然支持这种方式。外部访问项目时,采用ingress gateway方式。

项目分为3个服务(istio-client,istio-service1,istio-service2)。其中istio-client分别调用istio-service1和istio-service2。

★3.1.istio-client■■■■■■

1.项目结构

●SeataConfig.java

package com.istioclient.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.seata.spring.annotation.GlobalTransactionScanner;
@Configuration
public class SeataConfig {@Beanpublic GlobalTransactionScanner globalTransactionScanner() {return new GlobalTransactionScanner("istioClient-gts-seata", "istio_tx_group");}
}

●TestController.java

package com.istioclient.controller;
import com.istioclient.service.TestService;
import com.istioclient.util.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class TestController {private Logger logger = LoggerFactory.getLogger(TestController.class);@AutowiredTestService testService;@Autowiredprivate HttpUtil httpUtil;@Value("${istio.service1.url}")private String istioService1Url;@Value("${istio.service2.url}")private String istioService2Url;@RequestMapping("/getTest1")public String getTest1(){logger.info("#############getTest1");String res = httpUtil.callAService(istioService1Url + "/test1/getTest1");return res;}@RequestMapping("/getTest2")public String getTest2(){logger.info("#############getTest2");String res = httpUtil.callAService(istioService2Url + "/test2/getTest2");return res;}@RequestMapping("/seataTest")public String seataTest(){logger.info("#############seataTest");return testService.seataTest();}
}

●TestService.java

package com.istioclient.service;
import com.istioclient.util.HttpUtil;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;@Service
public class TestService {@Autowiredprivate HttpUtil httpUtil;@Value("${istio.service1.url}")private String istioService1Url;@Value("${istio.service2.url}")private String istioService2Url;@GlobalTransactionalpublic String 	seataTest(){String test1 = httpUtil.callAService(istioService1Url + "/test1/insertTest1");String test2 = httpUtil.callAService(istioService2Url + "/test2/insertTest4");return test1 + "||" + test2;}
}

●HttpUtil.java

package com.istioclient.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;@Component
public class HttpUtil {@Autowiredprivate RestTemplate restTemplate;public String callAService(String serviceUrl){try {//■■■组装headers 以下header用于istio服务网格追踪你的调用链,参数无需手动赋值HttpHeaders headers = new HttpHeaders();headers.add("x-request-id",null);headers.add("x-b3-traceid",null);headers.add("x-b3-spanid",null);headers.add("x-b3-parentspanid",null);headers.add("x-b3-sampled",null);headers.add("x-b3-flags",null);headers.add("x-ot-span-context",null);headers.add("x-cloud-trace-context",null);headers.add("traceparent",null);headers.add("grpc-trace-bin",null);//■■■组装请求参数Map<String, Object> requestBody = new HashMap<>();requestBody.put("key","value");HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(requestBody, headers);//参数1:访问url//参数2:返回值类型//参数3...:访问url带的参数列表
//			restTemplate.getForEntity(url,entity.class,Sting1,int2);
//			restTemplate.getForObject(url,Object.class,int1,long2);//参数1:访问url//参数2:访问url带的参数//参数3:返回的类型
//			restTemplate.postForEntity(url,entity,entity.class);return restTemplate.getForObject(serviceUrl, String.class,httpEntity);} catch (RestClientException e) {return e.getMessage();}}
}

●IstioCliApp.java

package com.istioclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;@SpringBootApplication
public class IstioCliApp {public static void main(String[] args) {try {ConfigurableApplicationContext ca = SpringApplication.run(IstioCliApp.class, args);System.out.println(System.getenv("SERVICES_DOMAIN"));System.out.println("■■■■■启动正常");}catch(Exception e){e.printStackTrace();System.out.println("■■■■■启动异常");}}@BeanRestTemplate restTemplate() {return new RestTemplate();}
}

●application.properties

spring.profiles.active=istioserver.port=8080###■■■■restTemplate连接池
#最大连接数
http.maxTotal=100
#并发数
http.defaultMaxPerRoute=20
#创建连接的最长时间
http.connectTimeout=1000
#从连接池中获取到连接的最长时间
http.connectionRequestTimeout=500
#数据传输的最长时间
http.socketTimeout=10000
#提交请求前测试连接是否可用
http.staleConnectionCheckEnabled=true
#可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间,如果超过,释放socket重新建立
http.validateAfterInactivity=3000000

●application-dev.properties

#istio-service1地址
istio.service1.url=http://localhost:8081#istio-service2地址
istio.service2.url=http://localhost:8082

●application-istio-properties

#istio-service1地址
istio.service1.url=http://10.108.232.20:8081#istio-service2地址
istio.service2.url=http://10.108.232.30:8082

●file.conf

transport {# tcp udt unix-domain-sockettype = "TCP"#NIO NATIVEserver = "NIO"#enable heartbeatheartbeat = true# the client batch send request enableenableClientBatchSendRequest = true#thread factory for nettythreadFactory {bossThreadPrefix = "NettyBoss"workerThreadPrefix = "NettyServerNIOWorker"serverExecutorThread-prefix = "NettyServerBizHandler"shareBossWorker = falseclientSelectorThreadPrefix = "NettyClientSelector"clientSelectorThreadSize = 1clientWorkerThreadPrefix = "NettyClientWorkerThread"# netty boss thread size,will not be used for UDTbossThreadSize = 1#auto default pin or 8workerThreadSize = "default"}shutdown {# when destroy server, wait secondswait = 3}serialization = "seata"compressor = "none"
}
service {#transaction service group mappingvgroupMapping.istio_tx_group = "default"#only support when registry.type=file, please don't set multiple addresses#■■■■■■■■■■■■■ seata 地址设置 start ■■■■■■■■■■■■■ default.grouplist = "172.22.70.72:8091"#■■■■■■■■■■■■■ seata 地址设置 end ■■■■■■■■■■■■■#degrade, current not supportenableDegrade = false#disable seatadisableGlobalTransaction = false
}client {rm {asyncCommitBufferLimit = 10000lock {retryInterval = 10retryTimes = 30retryPolicyBranchRollbackOnConflict = true}reportRetryCount = 5tableMetaCheckEnable = falsereportSuccessEnable = false}tm {commitRetryCount = 5rollbackRetryCount = 5}undo {dataValidation = truelogSerialization = "jackson"logTable = "undo_log"}log {exceptionRate = 100}
}

●log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO"><!-- ■■■■■ 要使这个配置生效,需要pom中排除掉spring-boot-starter-logging ■■■■■ --><!--全局参数--><Properties><!--%d{yyyy-MM-dd HH:mm:ss.SSS} =>格式化时间 2020-01-21 14:03:53.858%5p                         =>输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL%t                          =>输出产生该日志事件的线程名%c{1}                       =>输出日志信息所属的类目,通常就是所在类的全名%L                          =>输出代码中的行号%m                          =>输出代码中指定的消息,产生的日志具体信息%n                          =>输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"输出日志信息换行--><Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %t %c{1}:%L - %m%n</Property><!-- ■■■日志输出文件夹【不同项目在同一个目录下时,用日志文件夹区分不同项目日志】 --><Property name="logDir">clientLogs/</Property></Properties><Loggers><Root level="INFO"><AppenderRef ref="console"/><AppenderRef ref="asyncInfoLog"/><AppenderRef ref="asyncLogError"/></Root></Loggers><Appenders><!-- 定义输出到控制台 --><Console name="console" target="SYSTEM_OUT" follow="true"><!--控制台只输出level及以上级别的信息--><ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/><PatternLayout><Pattern>${pattern}</Pattern></PatternLayout></Console><!-- 同一来源的Appender可以定义多个RollingFile,定义按天存储日志 --><!-- INFO日志 --><RollingFile name="rolling_file_info" fileName="${logDir}/info_client.log"filePattern="${logDir}/info_client_%d{yyyy-MM-dd}.log"><Filters><ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/><ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/></Filters><PatternLayout><Pattern>${pattern}</Pattern></PatternLayout><Policies><TimeBasedTriggeringPolicy interval="1"/></Policies><!-- 日志保留策略,配置只保留180天 --><DefaultRolloverStrategy><Delete basePath="${logDir}/" maxDepth="1"><IfFileName glob="info_client_*.log"/><IfLastModified age="180d"/></Delete></DefaultRolloverStrategy></RollingFile><!-- ERROR日志 --><RollingFile name="rolling_file_error" fileName="${logDir}/error_client.log"filePattern="${logDir}/error_client_%d{yyyy-MM-dd}.log"><Filters><ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="NEUTRAL"/><ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/></Filters><PatternLayout><Pattern>${pattern}</Pattern></PatternLayout><Policies><TimeBasedTriggeringPolicy interval="1"/></Policies><!-- 日志保留策略,配置只保留180天 --><DefaultRolloverStrategy><Delete basePath="${logDir}/" maxDepth="1"><IfFileName glob="error_client_*.log"/><IfLastModified age="180d"/></Delete></DefaultRolloverStrategy></RollingFile><Async name="asyncInfoLog" includeLocation="true"><AppenderRef ref="rolling_file_info"/></Async><Async name="asyncLogError" includeLocation="true"><AppenderRef ref="rolling_file_error"/></Async></Appenders>
</Configuration>

●registry.conf

registry {# file 、nacos 、eureka、redis、zk、consul、etcd3、sofatype = "file"loadBalance = "RandomLoadBalance"loadBalanceVirtualNodes = 10nacos {application = "seata-server"serverAddr = "127.0.0.1:8848"group = "SEATA_GROUP"namespace = ""cluster = "default"username = ""password = ""}eureka {serviceUrl = "http://localhost:8761/eureka"application = "default"weight = "1"}redis {serverAddr = "localhost:6379"db = 0password = ""cluster = "default"timeout = 0}zk {cluster = "default"serverAddr = "127.0.0.1:2181"sessionTimeout = 6000connectTimeout = 2000username = ""password = ""}consul {cluster = "default"serverAddr = "127.0.0.1:8500"}etcd3 {cluster = "default"serverAddr = "http://localhost:2379"}sofa {serverAddr = "127.0.0.1:9603"application = "default"region = "DEFAULT_ZONE"datacenter = "DefaultDataCenter"cluster = "default"group = "SEATA_GROUP"addressWaitTime = "3000"}file {name = "file.conf"}
}config {# file、nacos 、apollo、zk、consul、etcd3type = "file"nacos {serverAddr = "127.0.0.1:8848"namespace = ""group = "SEATA_GROUP"username = ""password = ""}consul {serverAddr = "127.0.0.1:8500"}apollo {appId = "seata-server"apolloMeta = "http://192.168.1.204:8801"namespace = "application"apolloAccesskeySecret = ""}zk {serverAddr = "127.0.0.1:2181"sessionTimeout = 6000connectTimeout = 2000username = ""password = ""}etcd3 {serverAddr = "http://localhost:2379"}file {name = "file.conf"}
}

●pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns=".0.0" xmlns:xsi=""xsi:schemaLocation=".0.0 .0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.2</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com</groupId><artifactId>istio-client</artifactId><version>1.0</version><name>istio-client</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.6</version></dependency><!-- 分布式事务 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><version>2.2.6.RELEASE</version><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>1.4.1</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion></exclusions></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

★3.2.istio-service1■■■■■■

1.项目结构

●SeataConfig.java

package com.istioservice1.config;
import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import io.seata.spring.annotation.GlobalTransactionScanner;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;@Configuration
public class SeataConfig {@Value("${spring.datasource.url}")private String url;@Value("${spring.datasource.username}")private String username;@Value("${spring.datasource.password}")private String password;@Value("${spring.datasource.driverClassName}")private String driverClassName;@Bean@Primarypublic DruidDataSource druidDataSource(){DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setUrl(url);druidDataSource.setUsername(username);druidDataSource.setPassword(password);druidDataSource.setDriverClassName(driverClassName);// 初始连接数druidDataSource.setInitialSize(5);// 最小连接池数量druidDataSource.setMinIdle(10);// 最大连接池数量druidDataSource.setMaxActive(20);// 配置获取连接等待超时的时间druidDataSource.setMaxWait(60000);// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒druidDataSource.setTimeBetweenEvictionRunsMillis(60000);// 配置一个连接在池中最小生存的时间,单位是毫秒druidDataSource.setMinEvictableIdleTimeMillis(300000);// 配置一个连接在池中最大生存的时间,单位是毫秒druidDataSource.setMaxEvictableIdleTimeMillis(900000);// 配置检测连接是否有效druidDataSource.setValidationQuery("select 'x'");druidDataSource.setTestWhileIdle(true);druidDataSource.setTestOnBorrow(false);druidDataSource.setTestOnReturn(false);
//		druidDataSource.setRemoveAbandoned(true);
//		druidDataSource.setRemoveAbandonedTimeout(1800);
//		druidDataSource.setLogAbandoned(true);return druidDataSource;}@Beanpublic DataSourceProxy dataSourceProxy(DataSource druidDataSource) {return new DataSourceProxy(druidDataSource);}@Beanpublic SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy) throws Exception {SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSourceProxy);factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mybatis/mapper/*.xml"));factoryBean.setTransactionFactory(new JdbcTransactionFactory());return factoryBean.getObject();}@Beanpublic GlobalTransactionScanner globalTransactionScanner() {return new GlobalTransactionScanner("istioService1-gts-seata", "istio_tx_group");}
}

●Test1Controller.java

package com.istioservice1.controller;
import com.istioservice1.entity.Test1;
import com.istioservice1.service.Test1Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.Inet4Address;
import java.InetAddress;
import java.NetworkInterface;
import java.util.Enumeration;@RestController
@RequestMapping("/test1")
public class Test1Controller {private Logger logger = LoggerFactory.getLogger(Test1Controller.class);@AutowiredTest1Service test1Service;@RequestMapping("/getTest")public String getTest(){logger.info("$$$$$$$$$$$$getTest");return "hello";}@RequestMapping("/getTest1")public String getTest1(){logger.info("$$$$$$$$$$$$getTest1");String ip = getIp();Test1 test1=test1Service.getTest1ByKey(1);return "istio-service1 ip=" + ip + "|name = " + test1.getName();}@RequestMapping("/insertTest1")public String insertTest1(){logger.info("$$$$$$$$$$$$insertTest1");test1Service.insertTest1();return "ok";}public String getIp(){String ipAdd = "";try{Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();InetAddress ip = null;while (allNetInterfaces.hasMoreElements()){NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();System.out.println(netInterface.getName());Enumeration addresses = netInterface.getInetAddresses();while (addresses.hasMoreElements()){ip = (InetAddress) addresses.nextElement();if (ip != null && ip instanceof Inet4Address){ipAdd = ip.getHostAddress();System.out.println("本机的IP = " + ip.getHostAddress());}}}}catch (Exception e){e.printStackTrace();}return ipAdd;}
}

●Test1Mapper.java

package com.istioservice1.dao;
import com.istioservice1.entity.Test1;
import com.istioservice1.entity.Test1Example;
import java.util.List;
import org.apache.ibatis.annotations.Param;public interface Test1Mapper {int deleteByExample(Test1Example example);int deleteByPrimaryKey(Integer id);int insert(Test1 record);int insertSelective(Test1 record);List<Test1> selectByExample(Test1Example example);Test1 selectByPrimaryKey(Integer id);int updateByExampleSelective(@Param("record") Test1 record, @Param("example") Test1Example example);int updateByExample(@Param("record") Test1 record, @Param("example") Test1Example example);int updateByPrimaryKeySelective(Test1 record);int updateByPrimaryKey(Test1 record);
}

●Test4Mapper.java

package com.istioservice1.dao;
import com.istioservice1.entity.Test4;
import com.istioservice1.entity.Test4Example;
import java.util.List;
import org.apache.ibatis.annotations.Param;public interface Test4Mapper {int deleteByExample(Test4Example example);int deleteByPrimaryKey(Integer id);int insert(Test4 record);int insertSelective(Test4 record);List<Test4> selectByExample(Test4Example example);Test4 selectByPrimaryKey(Integer id);int updateByExampleSelective(@Param("record") Test4 record, @Param("example") Test4Example example);int updateByExample(@Param("record") Test4 record, @Param("example") Test4Example example);int updateByPrimaryKeySelective(Test4 record);int updateByPrimaryKey(Test4 record);
}

●Test1.java

package com.istioservice1.entity;public class Test1 {private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

●Test1Example.java

package com.istioservice1.entity;
import java.util.ArrayList;
import java.util.List;public class Test1Example {protected String orderByClause;protected boolean distinct;protected List<Criteria> oredCriteria;public Test1Example() {oredCriteria = new ArrayList<Criteria>();}public void setOrderByClause(String orderByClause) {this.orderByClause = orderByClause;}public String getOrderByClause() {return orderByClause;}public void setDistinct(boolean distinct) {this.distinct = distinct;}public boolean isDistinct() {return distinct;}public List<Criteria> getOredCriteria() {return oredCriteria;}public void or(Criteria criteria) {oredCriteria.add(criteria);}public Criteria or() {Criteria criteria = createCriteriaInternal();oredCriteria.add(criteria);return criteria;}public Criteria createCriteria() {Criteria criteria = createCriteriaInternal();if (oredCriteria.size() == 0) {oredCriteria.add(criteria);}return criteria;}protected Criteria createCriteriaInternal() {Criteria criteria = new Criteria();return criteria;}public void clear() {oredCriteria.clear();orderByClause = null;distinct = false;}protected abstract static class GeneratedCriteria {protected List<Criterion> criteria;protected GeneratedCriteria() {super();criteria = new ArrayList<Criterion>();}public boolean isValid() {return criteria.size() > 0;}public List<Criterion> getAllCriteria() {return criteria;}public List<Criterion> getCriteria() {return criteria;}protected void addCriterion(String condition) {if (condition == null) {throw new RuntimeException("Value for condition cannot be null");}criteria.add(new Criterion(condition));}protected void addCriterion(String condition, Object value, String property) {if (value == null) {throw new RuntimeException("Value for " + property + " cannot be null");}criteria.add(new Criterion(condition, value));}protected void addCriterion(String condition, Object value1, Object value2, String property) {if (value1 == null || value2 == null) {throw new RuntimeException("Between values for " + property + " cannot be null");}criteria.add(new Criterion(condition, value1, value2));}public Criteria andIdIsNull() {addCriterion("id is null");return (Criteria) this;}public Criteria andIdIsNotNull() {addCriterion("id is not null");return (Criteria) this;}public Criteria andIdEqualTo(Integer value) {addCriterion("id =", value, "id");return (Criteria) this;}public Criteria andIdNotEqualTo(Integer value) {addCriterion("id <>", value, "id");return (Criteria) this;}public Criteria andIdGreaterThan(Integer value) {addCriterion("id >", value, "id");return (Criteria) this;}public Criteria andIdGreaterThanOrEqualTo(Integer value) {addCriterion("id >=", value, "id");return (Criteria) this;}public Criteria andIdLessThan(Integer value) {addCriterion("id <", value, "id");return (Criteria) this;}public Criteria andIdLessThanOrEqualTo(Integer value) {addCriterion("id <=", value, "id");return (Criteria) this;}public Criteria andIdIn(List<Integer> values) {addCriterion("id in", values, "id");return (Criteria) this;}public Criteria andIdNotIn(List<Integer> values) {addCriterion("id not in", values, "id");return (Criteria) this;}public Criteria andIdBetween(Integer value1, Integer value2) {addCriterion("id between", value1, value2, "id");return (Criteria) this;}public Criteria andIdNotBetween(Integer value1, Integer value2) {addCriterion("id not between", value1, value2, "id");return (Criteria) this;}public Criteria andNameIsNull() {addCriterion("name is null");return (Criteria) this;}public Criteria andNameIsNotNull() {addCriterion("name is not null");return (Criteria) this;}public Criteria andNameEqualTo(String value) {addCriterion("name =", value, "name");return (Criteria) this;}public Criteria andNameNotEqualTo(String value) {addCriterion("name <>", value, "name");return (Criteria) this;}public Criteria andNameGreaterThan(String value) {addCriterion("name >", value, "name");return (Criteria) this;}public Criteria andNameGreaterThanOrEqualTo(String value) {addCriterion("name >=", value, "name");return (Criteria) this;}public Criteria andNameLessThan(String value) {addCriterion("name <", value, "name");return (Criteria) this;}public Criteria andNameLessThanOrEqualTo(String value) {addCriterion("name <=", value, "name");return (Criteria) this;}public Criteria andNameLike(String value) {addCriterion("name like", value, "name");return (Criteria) this;}public Criteria andNameNotLike(String value) {addCriterion("name not like", value, "name");return (Criteria) this;}public Criteria andNameIn(List<String> values) {addCriterion("name in", values, "name");return (Criteria) this;}public Criteria andNameNotIn(List<String> values) {addCriterion("name not in", values, "name");return (Criteria) this;}public Criteria andNameBetween(String value1, String value2) {addCriterion("name between", value1, value2, "name");return (Criteria) this;}public Criteria andNameNotBetween(String value1, String value2) {addCriterion("name not between", value1, value2, "name");return (Criteria) this;}}public static class Criteria extends GeneratedCriteria {protected Criteria() {super();}}public static class Criterion {private String condition;private Object value;private Object secondValue;private boolean noValue;private boolean singleValue;private boolean betweenValue;private boolean listValue;private String typeHandler;public String getCondition() {return condition;}public Object getValue() {return value;}public Object getSecondValue() {return secondValue;}public boolean isNoValue() {return noValue;}public boolean isSingleValue() {return singleValue;}public boolean isBetweenValue() {return betweenValue;}public boolean isListValue() {return listValue;}public String getTypeHandler() {return typeHandler;}protected Criterion(String condition) {super();this.condition = condition;this.typeHandler = null;this.noValue = true;}protected Criterion(String condition, Object value, String typeHandler) {super();this.condition = condition;this.value = value;this.typeHandler = typeHandler;if (value instanceof List<?>) {this.listValue = true;} else {this.singleValue = true;}}protected Criterion(String condition, Object value) {this(condition, value, null);}protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {super();this.condition = condition;this.value = value;this.secondValue = secondValue;this.typeHandler = typeHandler;this.betweenValue = true;}protected Criterion(String condition, Object value, Object secondValue) {this(condition, value, secondValue, null);}}
}

●Test4.java

package com.istioservice1.entity;public class Test4 {private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

●Test4Example.java

package com.istioservice1.entity;
import java.util.ArrayList;
import java.util.List;public class Test4Example {protected String orderByClause;protected boolean distinct;protected List<Criteria> oredCriteria;public Test4Example() {oredCriteria = new ArrayList<Criteria>();}public void setOrderByClause(String orderByClause) {this.orderByClause = orderByClause;}public String getOrderByClause() {return orderByClause;}public void setDistinct(boolean distinct) {this.distinct = distinct;}public boolean isDistinct() {return distinct;}public List<Criteria> getOredCriteria() {return oredCriteria;}public void or(Criteria criteria) {oredCriteria.add(criteria);}public Criteria or() {Criteria criteria = createCriteriaInternal();oredCriteria.add(criteria);return criteria;}public Criteria createCriteria() {Criteria criteria = createCriteriaInternal();if (oredCriteria.size() == 0) {oredCriteria.add(criteria);}return criteria;}protected Criteria createCriteriaInternal() {Criteria criteria = new Criteria();return criteria;}public void clear() {oredCriteria.clear();orderByClause = null;distinct = false;}protected abstract static class GeneratedCriteria {protected List<Criterion> criteria;protected GeneratedCriteria() {super();criteria = new ArrayList<Criterion>();}public boolean isValid() {return criteria.size() > 0;}public List<Criterion> getAllCriteria() {return criteria;}public List<Criterion> getCriteria() {return criteria;}protected void addCriterion(String condition) {if (condition == null) {throw new RuntimeException("Value for condition cannot be null");}criteria.add(new Criterion(condition));}protected void addCriterion(String condition, Object value, String property) {if (value == null) {throw new RuntimeException("Value for " + property + " cannot be null");}criteria.add(new Criterion(condition, value));}protected void addCriterion(String condition, Object value1, Object value2, String property) {if (value1 == null || value2 == null) {throw new RuntimeException("Between values for " + property + " cannot be null");}criteria.add(new Criterion(condition, value1, value2));}public Criteria andIdIsNull() {addCriterion("id is null");return (Criteria) this;}public Criteria andIdIsNotNull() {addCriterion("id is not null");return (Criteria) this;}public Criteria andIdEqualTo(Integer value) {addCriterion("id =", value, "id");return (Criteria) this;}public Criteria andIdNotEqualTo(Integer value) {addCriterion("id <>", value, "id");return (Criteria) this;}public Criteria andIdGreaterThan(Integer value) {addCriterion("id >", value, "id");return (Criteria) this;}public Criteria andIdGreaterThanOrEqualTo(Integer value) {addCriterion("id >=", value, "id");return (Criteria) this;}public Criteria andIdLessThan(Integer value) {addCriterion("id <", value, "id");return (Criteria) this;}public Criteria andIdLessThanOrEqualTo(Integer value) {addCriterion("id <=", value, "id");return (Criteria) this;}public Criteria andIdIn(List<Integer> values) {addCriterion("id in", values, "id");return (Criteria) this;}public Criteria andIdNotIn(List<Integer> values) {addCriterion("id not in", values, "id");return (Criteria) this;}public Criteria andIdBetween(Integer value1, Integer value2) {addCriterion("id between", value1, value2, "id");return (Criteria) this;}public Criteria andIdNotBetween(Integer value1, Integer value2) {addCriterion("id not between", value1, value2, "id");return (Criteria) this;}public Criteria andNameIsNull() {addCriterion("name is null");return (Criteria) this;}public Criteria andNameIsNotNull() {addCriterion("name is not null");return (Criteria) this;}public Criteria andNameEqualTo(String value) {addCriterion("name =", value, "name");return (Criteria) this;}public Criteria andNameNotEqualTo(String value) {addCriterion("name <>", value, "name");return (Criteria) this;}public Criteria andNameGreaterThan(String value) {addCriterion("name >", value, "name");return (Criteria) this;}public Criteria andNameGreaterThanOrEqualTo(String value) {addCriterion("name >=", value, "name");return (Criteria) this;}public Criteria andNameLessThan(String value) {addCriterion("name <", value, "name");return (Criteria) this;}public Criteria andNameLessThanOrEqualTo(String value) {addCriterion("name <=", value, "name");return (Criteria) this;}public Criteria andNameLike(String value) {addCriterion("name like", value, "name");return (Criteria) this;}public Criteria andNameNotLike(String value) {addCriterion("name not like", value, "name");return (Criteria) this;}public Criteria andNameIn(List<String> values) {addCriterion("name in", values, "name");return (Criteria) this;}public Criteria andNameNotIn(List<String> values) {addCriterion("name not in", values, "name");return (Criteria) this;}public Criteria andNameBetween(String value1, String value2) {addCriterion("name between", value1, value2, "name");return (Criteria) this;}public Criteria andNameNotBetween(String value1, String value2) {addCriterion("name not between", value1, value2, "name");return (Criteria) this;}}public static class Criteria extends GeneratedCriteria {protected Criteria() {super();}}public static class Criterion {private String condition;private Object value;private Object secondValue;private boolean noValue;private boolean singleValue;private boolean betweenValue;private boolean listValue;private String typeHandler;public String getCondition() {return condition;}public Object getValue() {return value;}public Object getSecondValue() {return secondValue;}public boolean isNoValue() {return noValue;}public boolean isSingleValue() {return singleValue;}public boolean isBetweenValue() {return betweenValue;}public boolean isListValue() {return listValue;}public String getTypeHandler() {return typeHandler;}protected Criterion(String condition) {super();this.condition = condition;this.typeHandler = null;this.noValue = true;}protected Criterion(String condition, Object value, String typeHandler) {super();this.condition = condition;this.value = value;this.typeHandler = typeHandler;if (value instanceof List<?>) {this.listValue = true;} else {this.singleValue = true;}}protected Criterion(String condition, Object value) {this(condition, value, null);}protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {super();this.condition = condition;this.value = value;this.secondValue = secondValue;this.typeHandler = typeHandler;this.betweenValue = true;}protected Criterion(String condition, Object value, Object secondValue) {this(condition, value, secondValue, null);}}
}

●Test1Service.java

package com.istioservice1.service;
import com.istioservice1.dao.Test1Mapper;
import com.istioservice1.entity.Test1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
@Transactional(rollbackFor = Exception.class)
public class Test1Service {@AutowiredTest1Mapper test1Mapper;public Test1 getTest1ByKey(int id){Test1 test1 = test1Mapper.selectByPrimaryKey(id);return test1;}public void insertTest1(){Test1 test1 = new Test1();test1.setId(99);test1.setName("liutao");test1Mapper.insert(test1);}
}

●IstioSvc1App.java

package com.istioservice1;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@MapperScan("com.istioservice1.dao")
@SpringBootApplication
public class IstioSvc1App {public static void main(String[] args) {SpringApplication.run(IstioSvc1App.class, args);}}

●Test1Mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis//DTD Mapper 3.0//EN" ".dtd">
<mapper namespace="com.istioservice1.dao.Test1Mapper"><resultMap id="BaseResultMap" type="com.istioservice1.entity.Test1"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><id column="id" jdbcType="INTEGER" property="id" /><result column="name" jdbcType="VARCHAR" property="name" /></resultMap><sql id="Example_Where_Clause"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><where><foreach collection="oredCriteria" item="criteria" separator="or"><if test="criteria.valid"><trim prefix="(" prefixOverrides="and" suffix=")"><foreach collection="criteria.criteria" item="criterion"><choose><when test="criterion.noValue">and ${criterion.condition}</when><when test="criterion.singleValue">and ${criterion.condition} #{criterion.value}</when><when test="criterion.betweenValue">and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}</when><when test="criterion.listValue">and ${criterion.condition}<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">#{listItem}</foreach></when></choose></foreach></trim></if></foreach></where></sql><sql id="Update_By_Example_Where_Clause"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><where><foreach collection="example.oredCriteria" item="criteria" separator="or"><if test="criteria.valid"><trim prefix="(" prefixOverrides="and" suffix=")"><foreach collection="criteria.criteria" item="criterion"><choose><when test="criterion.noValue">and ${criterion.condition}</when><when test="criterion.singleValue">and ${criterion.condition} #{criterion.value}</when><when test="criterion.betweenValue">and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}</when><when test="criterion.listValue">and ${criterion.condition}<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">#{listItem}</foreach></when></choose></foreach></trim></if></foreach></where></sql><sql id="Base_Column_List"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->id, name</sql><select id="selectByExample" parameterType="com.istioservice1.entity.Test1Example" resultMap="BaseResultMap"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->select<if test="distinct">distinct</if>'true' as QUERYID,<include refid="Base_Column_List" />from test1<if test="_parameter != null"><include refid="Example_Where_Clause" /></if><if test="orderByClause != null">order by ${orderByClause}</if></select><select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->select <include refid="Base_Column_List" />from test1where id = #{id,jdbcType=INTEGER}</select><delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->delete from test1where id = #{id,jdbcType=INTEGER}</delete><delete id="deleteByExample" parameterType="com.istioservice1.entity.Test1Example"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->delete from test1<if test="_parameter != null"><include refid="Example_Where_Clause" /></if></delete><insert id="insert" parameterType="com.istioservice1.entity.Test1"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->insert into test1 (id, name)values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR})</insert><insert id="insertSelective" parameterType="com.istioservice1.entity.Test1"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->insert into test1<trim prefix="(" suffix=")" suffixOverrides=","><if test="id != null">id,</if><if test="name != null">name,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="id != null">#{id,jdbcType=INTEGER},</if><if test="name != null">#{name,jdbcType=VARCHAR},</if></trim></insert><update id="updateByExampleSelective" parameterType="map"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test1<set><if test="record.id != null">id = #{record.id,jdbcType=INTEGER},</if><if test="record.name != null">name = #{record.name,jdbcType=VARCHAR},</if></set><if test="_parameter != null"><include refid="Update_By_Example_Where_Clause" /></if></update><update id="updateByExample" parameterType="map"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test1set id = #{record.id,jdbcType=INTEGER},name = #{record.name,jdbcType=VARCHAR}<if test="_parameter != null"><include refid="Update_By_Example_Where_Clause" /></if></update><update id="updateByPrimaryKeySelective" parameterType="com.istioservice1.entity.Test1"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test1<set><if test="name != null">name = #{name,jdbcType=VARCHAR},</if></set>where id = #{id,jdbcType=INTEGER}</update><update id="updateByPrimaryKey" parameterType="com.istioservice1.entity.Test1"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test1set name = #{name,jdbcType=VARCHAR}where id = #{id,jdbcType=INTEGER}</update>
</mapper>

●Test4Mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis//DTD Mapper 3.0//EN" ".dtd">
<mapper namespace="com.istioservice1.dao.Test4Mapper"><resultMap id="BaseResultMap" type="com.istioservice1.entity.Test4"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><id column="id" jdbcType="INTEGER" property="id" /><result column="name" jdbcType="VARCHAR" property="name" /></resultMap><sql id="Example_Where_Clause"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><where><foreach collection="oredCriteria" item="criteria" separator="or"><if test="criteria.valid"><trim prefix="(" prefixOverrides="and" suffix=")"><foreach collection="criteria.criteria" item="criterion"><choose><when test="criterion.noValue">and ${criterion.condition}</when><when test="criterion.singleValue">and ${criterion.condition} #{criterion.value}</when><when test="criterion.betweenValue">and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}</when><when test="criterion.listValue">and ${criterion.condition}<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">#{listItem}</foreach></when></choose></foreach></trim></if></foreach></where></sql><sql id="Update_By_Example_Where_Clause"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><where><foreach collection="example.oredCriteria" item="criteria" separator="or"><if test="criteria.valid"><trim prefix="(" prefixOverrides="and" suffix=")"><foreach collection="criteria.criteria" item="criterion"><choose><when test="criterion.noValue">and ${criterion.condition}</when><when test="criterion.singleValue">and ${criterion.condition} #{criterion.value}</when><when test="criterion.betweenValue">and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}</when><when test="criterion.listValue">and ${criterion.condition}<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">#{listItem}</foreach></when></choose></foreach></trim></if></foreach></where></sql><sql id="Base_Column_List"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->id, name</sql><select id="selectByExample" parameterType="com.istioservice1.entity.Test4Example" resultMap="BaseResultMap"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->select<if test="distinct">distinct</if>'true' as QUERYID,<include refid="Base_Column_List" />from test4<if test="_parameter != null"><include refid="Example_Where_Clause" /></if><if test="orderByClause != null">order by ${orderByClause}</if></select><select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->select <include refid="Base_Column_List" />from test4where id = #{id,jdbcType=INTEGER}</select><delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->delete from test4where id = #{id,jdbcType=INTEGER}</delete><delete id="deleteByExample" parameterType="com.istioservice1.entity.Test4Example"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->delete from test4<if test="_parameter != null"><include refid="Example_Where_Clause" /></if></delete><insert id="insert" parameterType="com.istioservice1.entity.Test4"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->insert into test4 (id, name)values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR})</insert><insert id="insertSelective" parameterType="com.istioservice1.entity.Test4"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->insert into test4<trim prefix="(" suffix=")" suffixOverrides=","><if test="id != null">id,</if><if test="name != null">name,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="id != null">#{id,jdbcType=INTEGER},</if><if test="name != null">#{name,jdbcType=VARCHAR},</if></trim></insert><update id="updateByExampleSelective" parameterType="map"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test4<set><if test="record.id != null">id = #{record.id,jdbcType=INTEGER},</if><if test="record.name != null">name = #{record.name,jdbcType=VARCHAR},</if></set><if test="_parameter != null"><include refid="Update_By_Example_Where_Clause" /></if></update><update id="updateByExample" parameterType="map"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test4set id = #{record.id,jdbcType=INTEGER},name = #{record.name,jdbcType=VARCHAR}<if test="_parameter != null"><include refid="Update_By_Example_Where_Clause" /></if></update><update id="updateByPrimaryKeySelective" parameterType="com.istioservice1.entity.Test4"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test4<set><if test="name != null">name = #{name,jdbcType=VARCHAR},</if></set>where id = #{id,jdbcType=INTEGER}</update><update id="updateByPrimaryKey" parameterType="com.istioservice1.entity.Test4"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test4set name = #{name,jdbcType=VARCHAR}where id = #{id,jdbcType=INTEGER}</update>
</mapper>

●application.properties

server.port=8081#本地测试用
spring.datasource.url=jdbc:postgresql://2.0.0.1:5432/test1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
#k8s测试用
#spring.datasource.url=jdbc:postgresql://10.108.206.185:5432/test1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driverClassName=org.postgresql.Driver
#mybatis.config-location=classpath:mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis.type-aliases-package=com.istioservice1.entity

●file.conf

transport {# tcp udt unix-domain-sockettype = "TCP"#NIO NATIVEserver = "NIO"#enable heartbeatheartbeat = true# the client batch send request enableenableClientBatchSendRequest = true#thread factory for nettythreadFactory {bossThreadPrefix = "NettyBoss"workerThreadPrefix = "NettyServerNIOWorker"serverExecutorThread-prefix = "NettyServerBizHandler"shareBossWorker = falseclientSelectorThreadPrefix = "NettyClientSelector"clientSelectorThreadSize = 1clientWorkerThreadPrefix = "NettyClientWorkerThread"# netty boss thread size,will not be used for UDTbossThreadSize = 1#auto default pin or 8workerThreadSize = "default"}shutdown {# when destroy server, wait secondswait = 3}serialization = "seata"compressor = "none"
}
service {#transaction service group mappingvgroupMapping.istio_tx_group = "default"#only support when registry.type=file, please don't set multiple addresses#■■■■■■■■■■■■■ seata 地址设置 start ■■■■■■■■■■■■■default.grouplist = "172.22.70.72:8091"#■■■■■■■■■■■■■ seata 地址设置 end ■■■■■■■■■■■■■#degrade, current not supportenableDegrade = false#disable seatadisableGlobalTransaction = false
}client {rm {asyncCommitBufferLimit = 10000lock {retryInterval = 10retryTimes = 30retryPolicyBranchRollbackOnConflict = true}reportRetryCount = 5tableMetaCheckEnable = falsereportSuccessEnable = false}tm {commitRetryCount = 5rollbackRetryCount = 5}undo {dataValidation = truelogSerialization = "jackson"logTable = "undo_log"}log {exceptionRate = 100}
}

●log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO"><!-- ■■■■■ 要使这个配置生效,需要pom中排除掉spring-boot-starter-logging ■■■■■ --><!--全局参数--><Properties><!--%d{yyyy-MM-dd HH:mm:ss.SSS} =>格式化时间 2020-01-21 14:03:53.858%5p                         =>输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL%t                          =>输出产生该日志事件的线程名%c{1}                       =>输出日志信息所属的类目,通常就是所在类的全名%L                          =>输出代码中的行号%m                          =>输出代码中指定的消息,产生的日志具体信息%n                          =>输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"输出日志信息换行--><Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %t %c{1}:%L - %m%n</Property><!-- ■■■日志输出文件夹【不同项目在同一个目录下时,用日志文件夹区分不同项目日志】 --><Property name="logDir">service1Logs/</Property></Properties><Loggers><Root level="INFO"><AppenderRef ref="console"/><AppenderRef ref="asyncInfoLog"/><AppenderRef ref="asyncLogError"/></Root></Loggers><Appenders><!-- 定义输出到控制台 --><Console name="console" target="SYSTEM_OUT" follow="true"><!--控制台只输出level及以上级别的信息--><ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/><PatternLayout><Pattern>${pattern}</Pattern></PatternLayout></Console><!-- 同一来源的Appender可以定义多个RollingFile,定义按天存储日志 --><!-- INFO日志 --><RollingFile name="rolling_file_info" fileName="${logDir}/info_service1.log"filePattern="${logDir}/info_service1_%d{yyyy-MM-dd}.log"><Filters><ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/><ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/></Filters><PatternLayout><Pattern>${pattern}</Pattern></PatternLayout><Policies><TimeBasedTriggeringPolicy interval="1"/></Policies><!-- 日志保留策略,配置只保留180天 --><DefaultRolloverStrategy><Delete basePath="${logDir}/" maxDepth="1"><IfFileName glob="info_service1_*.log"/><IfLastModified age="180d"/></Delete></DefaultRolloverStrategy></RollingFile><!-- ERROR日志 --><RollingFile name="rolling_file_error" fileName="${logDir}/error_service1.log"filePattern="${logDir}/error_service1_%d{yyyy-MM-dd}.log"><Filters><ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="NEUTRAL"/><ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/></Filters><PatternLayout><Pattern>${pattern}</Pattern></PatternLayout><Policies><TimeBasedTriggeringPolicy interval="1"/></Policies><!-- 日志保留策略,配置只保留180天 --><DefaultRolloverStrategy><Delete basePath="${logDir}/" maxDepth="1"><IfFileName glob="error_service1_*.log"/><IfLastModified age="180d"/></Delete></DefaultRolloverStrategy></RollingFile><Async name="asyncInfoLog" includeLocation="true"><AppenderRef ref="rolling_file_info"/></Async><Async name="asyncLogError" includeLocation="true"><AppenderRef ref="rolling_file_error"/></Async></Appenders>
</Configuration>

●registry.conf

registry {# file 、nacos 、eureka、redis、zk、consul、etcd3、sofatype = "file"loadBalance = "RandomLoadBalance"loadBalanceVirtualNodes = 10nacos {application = "seata-server"serverAddr = "127.0.0.1:8848"group = "SEATA_GROUP"namespace = ""cluster = "default"username = ""password = ""}eureka {serviceUrl = "http://localhost:8761/eureka"application = "default"weight = "1"}redis {serverAddr = "localhost:6379"db = 0password = ""cluster = "default"timeout = 0}zk {cluster = "default"serverAddr = "127.0.0.1:2181"sessionTimeout = 6000connectTimeout = 2000username = ""password = ""}consul {cluster = "default"serverAddr = "127.0.0.1:8500"}etcd3 {cluster = "default"serverAddr = "http://localhost:2379"}sofa {serverAddr = "127.0.0.1:9603"application = "default"region = "DEFAULT_ZONE"datacenter = "DefaultDataCenter"cluster = "default"group = "SEATA_GROUP"addressWaitTime = "3000"}file {name = "file.conf"}
}config {# file、nacos 、apollo、zk、consul、etcd3type = "file"nacos {serverAddr = "127.0.0.1:8848"namespace = ""group = "SEATA_GROUP"username = ""password = ""}consul {serverAddr = "127.0.0.1:8500"}apollo {appId = "seata-server"apolloMeta = "http://192.168.1.204:8801"namespace = "application"apolloAccesskeySecret = ""}zk {serverAddr = "127.0.0.1:2181"sessionTimeout = 6000connectTimeout = 2000username = ""password = ""}etcd3 {serverAddr = "http://localhost:2379"}file {name = "file.conf"}
}

●pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns=".0.0" xmlns:xsi=""xsi:schemaLocation=".0.0 .0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.2</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com</groupId><artifactId>istio-service1</artifactId><version>1.0</version><name>istio-service1</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.0.0</version></dependency><!-- 分布式事务 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><version>2.2.6.RELEASE</version><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>1.4.1</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion></exclusions></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

★3.3.istio-service2■■■■■■

1.项目结构

●SeataConfig.java

package com.istioservice2.config;
import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import io.seata.spring.annotation.GlobalTransactionScanner;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;@Configuration
public class SeataConfig {@Value("${spring.datasource.url}")private String url;@Value("${spring.datasource.username}")private String username;@Value("${spring.datasource.password}")private String password;@Value("${spring.datasource.driverClassName}")private String driverClassName;@Bean@Primarypublic DruidDataSource druidDataSource(){DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setUrl(url);druidDataSource.setUsername(username);druidDataSource.setPassword(password);druidDataSource.setDriverClassName(driverClassName);// 初始连接数druidDataSource.setInitialSize(5);// 最小连接池数量druidDataSource.setMinIdle(10);// 最大连接池数量druidDataSource.setMaxActive(20);// 配置获取连接等待超时的时间druidDataSource.setMaxWait(60000);// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒druidDataSource.setTimeBetweenEvictionRunsMillis(60000);// 配置一个连接在池中最小生存的时间,单位是毫秒druidDataSource.setMinEvictableIdleTimeMillis(300000);// 配置一个连接在池中最大生存的时间,单位是毫秒druidDataSource.setMaxEvictableIdleTimeMillis(900000);// 配置检测连接是否有效druidDataSource.setValidationQuery("select 'x'");druidDataSource.setTestWhileIdle(true);druidDataSource.setTestOnBorrow(false);druidDataSource.setTestOnReturn(false);
//		druidDataSource.setRemoveAbandoned(true);
//		druidDataSource.setRemoveAbandonedTimeout(1800);
//		druidDataSource.setLogAbandoned(true);return druidDataSource;}@Beanpublic DataSourceProxy dataSourceProxy(DataSource druidDataSource) {return new DataSourceProxy(druidDataSource);}@Beanpublic SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy) throws Exception {SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSourceProxy);factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mybatis/mapper/*.xml"));factoryBean.setTransactionFactory(new JdbcTransactionFactory());return factoryBean.getObject();}@Beanpublic GlobalTransactionScanner globalTransactionScanner() {return new GlobalTransactionScanner("istioService2-gts-seata", "istio_tx_group");}
}

 ●Test2Controller.java

package com.istioservice2.controller;
import com.istioservice2.entity.Test1;
import com.istioservice2.service.Test2Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/test2")
public class Test2Controller {private Logger logger = LoggerFactory.getLogger(Test2Controller.class);@AutowiredTest2Service test2Service;@RequestMapping("/getTest2")public String getTest2(){logger.info("%%%%%%%%%%%%%%getTest2");Test1 test1=test2Service.getTest1ByKey(2);return "istio-service2" + "| name =" + test1.getName();}@RequestMapping("/insertTest4")public String insertTest4(){logger.info("%%%%%%%%%%%%%%insertTest4");test2Service.insertTest4();return "ok";}
}

 ●Test1Mapper.java

package com.istioservice2.dao;
import com.istioservice2.entity.Test1;
import com.istioservice2.entity.Test1Example;
import java.util.List;
import org.apache.ibatis.annotations.Param;public interface Test1Mapper {int deleteByExample(Test1Example example);int deleteByPrimaryKey(Integer id);int insert(Test1 record);int insertSelective(Test1 record);List<Test1> selectByExample(Test1Example example);Test1 selectByPrimaryKey(Integer id);int updateByExampleSelective(@Param("record") Test1 record, @Param("example") Test1Example example);int updateByExample(@Param("record") Test1 record, @Param("example") Test1Example example);int updateByPrimaryKeySelective(Test1 record);int updateByPrimaryKey(Test1 record);
}

●Test4Mapper.java

package com.istioservice2.dao;
import com.istioservice2.entity.Test4;
import com.istioservice2.entity.Test4Example;
import java.util.List;
import org.apache.ibatis.annotations.Param;public interface Test4Mapper {int deleteByExample(Test4Example example);int deleteByPrimaryKey(Integer id);int insert(Test4 record);int insertSelective(Test4 record);List<Test4> selectByExample(Test4Example example);Test4 selectByPrimaryKey(Integer id);int updateByExampleSelective(@Param("record") Test4 record, @Param("example") Test4Example example);int updateByExample(@Param("record") Test4 record, @Param("example") Test4Example example);int updateByPrimaryKeySelective(Test4 record);int updateByPrimaryKey(Test4 record);
}

●Test1.java

package com.istioservice2.entity;public class Test1 {private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

●Test1Example.java

package com.istioservice2.entity;import java.util.ArrayList;
import java.util.List;public class Test1Example {protected String orderByClause;protected boolean distinct;protected List<Criteria> oredCriteria;public Test1Example() {oredCriteria = new ArrayList<Criteria>();}public void setOrderByClause(String orderByClause) {this.orderByClause = orderByClause;}public String getOrderByClause() {return orderByClause;}public void setDistinct(boolean distinct) {this.distinct = distinct;}public boolean isDistinct() {return distinct;}public List<Criteria> getOredCriteria() {return oredCriteria;}public void or(Criteria criteria) {oredCriteria.add(criteria);}public Criteria or() {Criteria criteria = createCriteriaInternal();oredCriteria.add(criteria);return criteria;}public Criteria createCriteria() {Criteria criteria = createCriteriaInternal();if (oredCriteria.size() == 0) {oredCriteria.add(criteria);}return criteria;}protected Criteria createCriteriaInternal() {Criteria criteria = new Criteria();return criteria;}public void clear() {oredCriteria.clear();orderByClause = null;distinct = false;}protected abstract static class GeneratedCriteria {protected List<Criterion> criteria;protected GeneratedCriteria() {super();criteria = new ArrayList<Criterion>();}public boolean isValid() {return criteria.size() > 0;}public List<Criterion> getAllCriteria() {return criteria;}public List<Criterion> getCriteria() {return criteria;}protected void addCriterion(String condition) {if (condition == null) {throw new RuntimeException("Value for condition cannot be null");}criteria.add(new Criterion(condition));}protected void addCriterion(String condition, Object value, String property) {if (value == null) {throw new RuntimeException("Value for " + property + " cannot be null");}criteria.add(new Criterion(condition, value));}protected void addCriterion(String condition, Object value1, Object value2, String property) {if (value1 == null || value2 == null) {throw new RuntimeException("Between values for " + property + " cannot be null");}criteria.add(new Criterion(condition, value1, value2));}public Criteria andIdIsNull() {addCriterion("id is null");return (Criteria) this;}public Criteria andIdIsNotNull() {addCriterion("id is not null");return (Criteria) this;}public Criteria andIdEqualTo(Integer value) {addCriterion("id =", value, "id");return (Criteria) this;}public Criteria andIdNotEqualTo(Integer value) {addCriterion("id <>", value, "id");return (Criteria) this;}public Criteria andIdGreaterThan(Integer value) {addCriterion("id >", value, "id");return (Criteria) this;}public Criteria andIdGreaterThanOrEqualTo(Integer value) {addCriterion("id >=", value, "id");return (Criteria) this;}public Criteria andIdLessThan(Integer value) {addCriterion("id <", value, "id");return (Criteria) this;}public Criteria andIdLessThanOrEqualTo(Integer value) {addCriterion("id <=", value, "id");return (Criteria) this;}public Criteria andIdIn(List<Integer> values) {addCriterion("id in", values, "id");return (Criteria) this;}public Criteria andIdNotIn(List<Integer> values) {addCriterion("id not in", values, "id");return (Criteria) this;}public Criteria andIdBetween(Integer value1, Integer value2) {addCriterion("id between", value1, value2, "id");return (Criteria) this;}public Criteria andIdNotBetween(Integer value1, Integer value2) {addCriterion("id not between", value1, value2, "id");return (Criteria) this;}public Criteria andNameIsNull() {addCriterion("name is null");return (Criteria) this;}public Criteria andNameIsNotNull() {addCriterion("name is not null");return (Criteria) this;}public Criteria andNameEqualTo(String value) {addCriterion("name =", value, "name");return (Criteria) this;}public Criteria andNameNotEqualTo(String value) {addCriterion("name <>", value, "name");return (Criteria) this;}public Criteria andNameGreaterThan(String value) {addCriterion("name >", value, "name");return (Criteria) this;}public Criteria andNameGreaterThanOrEqualTo(String value) {addCriterion("name >=", value, "name");return (Criteria) this;}public Criteria andNameLessThan(String value) {addCriterion("name <", value, "name");return (Criteria) this;}public Criteria andNameLessThanOrEqualTo(String value) {addCriterion("name <=", value, "name");return (Criteria) this;}public Criteria andNameLike(String value) {addCriterion("name like", value, "name");return (Criteria) this;}public Criteria andNameNotLike(String value) {addCriterion("name not like", value, "name");return (Criteria) this;}public Criteria andNameIn(List<String> values) {addCriterion("name in", values, "name");return (Criteria) this;}public Criteria andNameNotIn(List<String> values) {addCriterion("name not in", values, "name");return (Criteria) this;}public Criteria andNameBetween(String value1, String value2) {addCriterion("name between", value1, value2, "name");return (Criteria) this;}public Criteria andNameNotBetween(String value1, String value2) {addCriterion("name not between", value1, value2, "name");return (Criteria) this;}}public static class Criteria extends GeneratedCriteria {protected Criteria() {super();}}public static class Criterion {private String condition;private Object value;private Object secondValue;private boolean noValue;private boolean singleValue;private boolean betweenValue;private boolean listValue;private String typeHandler;public String getCondition() {return condition;}public Object getValue() {return value;}public Object getSecondValue() {return secondValue;}public boolean isNoValue() {return noValue;}public boolean isSingleValue() {return singleValue;}public boolean isBetweenValue() {return betweenValue;}public boolean isListValue() {return listValue;}public String getTypeHandler() {return typeHandler;}protected Criterion(String condition) {super();this.condition = condition;this.typeHandler = null;this.noValue = true;}protected Criterion(String condition, Object value, String typeHandler) {super();this.condition = condition;this.value = value;this.typeHandler = typeHandler;if (value instanceof List<?>) {this.listValue = true;} else {this.singleValue = true;}}protected Criterion(String condition, Object value) {this(condition, value, null);}protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {super();this.condition = condition;this.value = value;this.secondValue = secondValue;this.typeHandler = typeHandler;this.betweenValue = true;}protected Criterion(String condition, Object value, Object secondValue) {this(condition, value, secondValue, null);}}
}

●Test4.java

package com.istioservice2.entity;public class Test4 {private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

●Test4Example.java

package com.istioservice2.entity;import java.util.ArrayList;
import java.util.List;public class Test4Example {protected String orderByClause;protected boolean distinct;protected List<Criteria> oredCriteria;public Test4Example() {oredCriteria = new ArrayList<Criteria>();}public void setOrderByClause(String orderByClause) {this.orderByClause = orderByClause;}public String getOrderByClause() {return orderByClause;}public void setDistinct(boolean distinct) {this.distinct = distinct;}public boolean isDistinct() {return distinct;}public List<Criteria> getOredCriteria() {return oredCriteria;}public void or(Criteria criteria) {oredCriteria.add(criteria);}public Criteria or() {Criteria criteria = createCriteriaInternal();oredCriteria.add(criteria);return criteria;}public Criteria createCriteria() {Criteria criteria = createCriteriaInternal();if (oredCriteria.size() == 0) {oredCriteria.add(criteria);}return criteria;}protected Criteria createCriteriaInternal() {Criteria criteria = new Criteria();return criteria;}public void clear() {oredCriteria.clear();orderByClause = null;distinct = false;}protected abstract static class GeneratedCriteria {protected List<Criterion> criteria;protected GeneratedCriteria() {super();criteria = new ArrayList<Criterion>();}public boolean isValid() {return criteria.size() > 0;}public List<Criterion> getAllCriteria() {return criteria;}public List<Criterion> getCriteria() {return criteria;}protected void addCriterion(String condition) {if (condition == null) {throw new RuntimeException("Value for condition cannot be null");}criteria.add(new Criterion(condition));}protected void addCriterion(String condition, Object value, String property) {if (value == null) {throw new RuntimeException("Value for " + property + " cannot be null");}criteria.add(new Criterion(condition, value));}protected void addCriterion(String condition, Object value1, Object value2, String property) {if (value1 == null || value2 == null) {throw new RuntimeException("Between values for " + property + " cannot be null");}criteria.add(new Criterion(condition, value1, value2));}public Criteria andIdIsNull() {addCriterion("id is null");return (Criteria) this;}public Criteria andIdIsNotNull() {addCriterion("id is not null");return (Criteria) this;}public Criteria andIdEqualTo(Integer value) {addCriterion("id =", value, "id");return (Criteria) this;}public Criteria andIdNotEqualTo(Integer value) {addCriterion("id <>", value, "id");return (Criteria) this;}public Criteria andIdGreaterThan(Integer value) {addCriterion("id >", value, "id");return (Criteria) this;}public Criteria andIdGreaterThanOrEqualTo(Integer value) {addCriterion("id >=", value, "id");return (Criteria) this;}public Criteria andIdLessThan(Integer value) {addCriterion("id <", value, "id");return (Criteria) this;}public Criteria andIdLessThanOrEqualTo(Integer value) {addCriterion("id <=", value, "id");return (Criteria) this;}public Criteria andIdIn(List<Integer> values) {addCriterion("id in", values, "id");return (Criteria) this;}public Criteria andIdNotIn(List<Integer> values) {addCriterion("id not in", values, "id");return (Criteria) this;}public Criteria andIdBetween(Integer value1, Integer value2) {addCriterion("id between", value1, value2, "id");return (Criteria) this;}public Criteria andIdNotBetween(Integer value1, Integer value2) {addCriterion("id not between", value1, value2, "id");return (Criteria) this;}public Criteria andNameIsNull() {addCriterion("name is null");return (Criteria) this;}public Criteria andNameIsNotNull() {addCriterion("name is not null");return (Criteria) this;}public Criteria andNameEqualTo(String value) {addCriterion("name =", value, "name");return (Criteria) this;}public Criteria andNameNotEqualTo(String value) {addCriterion("name <>", value, "name");return (Criteria) this;}public Criteria andNameGreaterThan(String value) {addCriterion("name >", value, "name");return (Criteria) this;}public Criteria andNameGreaterThanOrEqualTo(String value) {addCriterion("name >=", value, "name");return (Criteria) this;}public Criteria andNameLessThan(String value) {addCriterion("name <", value, "name");return (Criteria) this;}public Criteria andNameLessThanOrEqualTo(String value) {addCriterion("name <=", value, "name");return (Criteria) this;}public Criteria andNameLike(String value) {addCriterion("name like", value, "name");return (Criteria) this;}public Criteria andNameNotLike(String value) {addCriterion("name not like", value, "name");return (Criteria) this;}public Criteria andNameIn(List<String> values) {addCriterion("name in", values, "name");return (Criteria) this;}public Criteria andNameNotIn(List<String> values) {addCriterion("name not in", values, "name");return (Criteria) this;}public Criteria andNameBetween(String value1, String value2) {addCriterion("name between", value1, value2, "name");return (Criteria) this;}public Criteria andNameNotBetween(String value1, String value2) {addCriterion("name not between", value1, value2, "name");return (Criteria) this;}}public static class Criteria extends GeneratedCriteria {protected Criteria() {super();}}public static class Criterion {private String condition;private Object value;private Object secondValue;private boolean noValue;private boolean singleValue;private boolean betweenValue;private boolean listValue;private String typeHandler;public String getCondition() {return condition;}public Object getValue() {return value;}public Object getSecondValue() {return secondValue;}public boolean isNoValue() {return noValue;}public boolean isSingleValue() {return singleValue;}public boolean isBetweenValue() {return betweenValue;}public boolean isListValue() {return listValue;}public String getTypeHandler() {return typeHandler;}protected Criterion(String condition) {super();this.condition = condition;this.typeHandler = null;this.noValue = true;}protected Criterion(String condition, Object value, String typeHandler) {super();this.condition = condition;this.value = value;this.typeHandler = typeHandler;if (value instanceof List<?>) {this.listValue = true;} else {this.singleValue = true;}}protected Criterion(String condition, Object value) {this(condition, value, null);}protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {super();this.condition = condition;this.value = value;this.secondValue = secondValue;this.typeHandler = typeHandler;this.betweenValue = true;}protected Criterion(String condition, Object value, Object secondValue) {this(condition, value, secondValue, null);}}
}

●Test2Service.java

package com.istioservice2.service;
import com.istioservice2.dao.Test1Mapper;
import com.istioservice2.dao.Test4Mapper;
import com.istioservice2.entity.Test1;
import com.istioservice2.entity.Test4;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
@Transactional(rollbackFor = Exception.class)
public class Test2Service {@AutowiredTest1Mapper test1Mapper;@AutowiredTest4Mapper test4Mapper;public Test1 getTest1ByKey(int id){Test1 test1 = test1Mapper.selectByPrimaryKey(id);return test1;}public void insertTest4(){Test4 test4 = new Test4();test4.setId(98);test4.setName("sharpfire");test4Mapper.insert(test4);int i = 1/0;}
}

●IstioSvc2App.java

package com.istioservice2;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;@EnableTransactionManagement
@MapperScan("com.istioservice2.dao")
@SpringBootApplication
public class IstioSvc2App {public static void main(String[] args) {SpringApplication.run(IstioSvc2App.class, args);}}

Test1Mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis//DTD Mapper 3.0//EN" ".dtd">
<mapper namespace="com.istioservice2.dao.Test1Mapper"><resultMap id="BaseResultMap" type="com.istioservice2.entity.Test1"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><id column="id" jdbcType="INTEGER" property="id" /><result column="name" jdbcType="VARCHAR" property="name" /></resultMap><sql id="Example_Where_Clause"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><where><foreach collection="oredCriteria" item="criteria" separator="or"><if test="criteria.valid"><trim prefix="(" prefixOverrides="and" suffix=")"><foreach collection="criteria.criteria" item="criterion"><choose><when test="criterion.noValue">and ${criterion.condition}</when><when test="criterion.singleValue">and ${criterion.condition} #{criterion.value}</when><when test="criterion.betweenValue">and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}</when><when test="criterion.listValue">and ${criterion.condition}<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">#{listItem}</foreach></when></choose></foreach></trim></if></foreach></where></sql><sql id="Update_By_Example_Where_Clause"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><where><foreach collection="example.oredCriteria" item="criteria" separator="or"><if test="criteria.valid"><trim prefix="(" prefixOverrides="and" suffix=")"><foreach collection="criteria.criteria" item="criterion"><choose><when test="criterion.noValue">and ${criterion.condition}</when><when test="criterion.singleValue">and ${criterion.condition} #{criterion.value}</when><when test="criterion.betweenValue">and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}</when><when test="criterion.listValue">and ${criterion.condition}<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">#{listItem}</foreach></when></choose></foreach></trim></if></foreach></where></sql><sql id="Base_Column_List"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->id, name</sql><select id="selectByExample" parameterType="com.istioservice2.entity.Test1Example" resultMap="BaseResultMap"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->select<if test="distinct">distinct</if>'true' as QUERYID,<include refid="Base_Column_List" />from test1<if test="_parameter != null"><include refid="Example_Where_Clause" /></if><if test="orderByClause != null">order by ${orderByClause}</if></select><select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->select <include refid="Base_Column_List" />from test1where id = #{id,jdbcType=INTEGER}</select><delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->delete from test1where id = #{id,jdbcType=INTEGER}</delete><delete id="deleteByExample" parameterType="com.istioservice2.entity.Test1Example"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->delete from test1<if test="_parameter != null"><include refid="Example_Where_Clause" /></if></delete><insert id="insert" parameterType="com.istioservice2.entity.Test1"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->insert into test1 (id, name)values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR})</insert><insert id="insertSelective" parameterType="com.istioservice2.entity.Test1"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->insert into test1<trim prefix="(" suffix=")" suffixOverrides=","><if test="id != null">id,</if><if test="name != null">name,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="id != null">#{id,jdbcType=INTEGER},</if><if test="name != null">#{name,jdbcType=VARCHAR},</if></trim></insert><update id="updateByExampleSelective" parameterType="map"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test1<set><if test="record.id != null">id = #{record.id,jdbcType=INTEGER},</if><if test="record.name != null">name = #{record.name,jdbcType=VARCHAR},</if></set><if test="_parameter != null"><include refid="Update_By_Example_Where_Clause" /></if></update><update id="updateByExample" parameterType="map"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test1set id = #{record.id,jdbcType=INTEGER},name = #{record.name,jdbcType=VARCHAR}<if test="_parameter != null"><include refid="Update_By_Example_Where_Clause" /></if></update><update id="updateByPrimaryKeySelective" parameterType="com.istioservice2.entity.Test1"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test1<set><if test="name != null">name = #{name,jdbcType=VARCHAR},</if></set>where id = #{id,jdbcType=INTEGER}</update><update id="updateByPrimaryKey" parameterType="com.istioservice2.entity.Test1"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test1set name = #{name,jdbcType=VARCHAR}where id = #{id,jdbcType=INTEGER}</update>
</mapper>

●Test4Mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis//DTD Mapper 3.0//EN" ".dtd">
<mapper namespace="com.istioservice2.dao.Test4Mapper"><resultMap id="BaseResultMap" type="com.istioservice2.entity.Test4"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><id column="id" jdbcType="INTEGER" property="id" /><result column="name" jdbcType="VARCHAR" property="name" /></resultMap><sql id="Example_Where_Clause"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><where><foreach collection="oredCriteria" item="criteria" separator="or"><if test="criteria.valid"><trim prefix="(" prefixOverrides="and" suffix=")"><foreach collection="criteria.criteria" item="criterion"><choose><when test="criterion.noValue">and ${criterion.condition}</when><when test="criterion.singleValue">and ${criterion.condition} #{criterion.value}</when><when test="criterion.betweenValue">and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}</when><when test="criterion.listValue">and ${criterion.condition}<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">#{listItem}</foreach></when></choose></foreach></trim></if></foreach></where></sql><sql id="Update_By_Example_Where_Clause"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.--><where><foreach collection="example.oredCriteria" item="criteria" separator="or"><if test="criteria.valid"><trim prefix="(" prefixOverrides="and" suffix=")"><foreach collection="criteria.criteria" item="criterion"><choose><when test="criterion.noValue">and ${criterion.condition}</when><when test="criterion.singleValue">and ${criterion.condition} #{criterion.value}</when><when test="criterion.betweenValue">and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}</when><when test="criterion.listValue">and ${criterion.condition}<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">#{listItem}</foreach></when></choose></foreach></trim></if></foreach></where></sql><sql id="Base_Column_List"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->id, name</sql><select id="selectByExample" parameterType="com.istioservice2.entity.Test4Example" resultMap="BaseResultMap"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->select<if test="distinct">distinct</if>'true' as QUERYID,<include refid="Base_Column_List" />from test4<if test="_parameter != null"><include refid="Example_Where_Clause" /></if><if test="orderByClause != null">order by ${orderByClause}</if></select><select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->select <include refid="Base_Column_List" />from test4where id = #{id,jdbcType=INTEGER}</select><delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->delete from test4where id = #{id,jdbcType=INTEGER}</delete><delete id="deleteByExample" parameterType="com.istioservice2.entity.Test4Example"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->delete from test4<if test="_parameter != null"><include refid="Example_Where_Clause" /></if></delete><insert id="insert" parameterType="com.istioservice2.entity.Test4"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->insert into test4 (id, name)values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR})</insert><insert id="insertSelective" parameterType="com.istioservice2.entity.Test4"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->insert into test4<trim prefix="(" suffix=")" suffixOverrides=","><if test="id != null">id,</if><if test="name != null">name,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="id != null">#{id,jdbcType=INTEGER},</if><if test="name != null">#{name,jdbcType=VARCHAR},</if></trim></insert><update id="updateByExampleSelective" parameterType="map"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test4<set><if test="record.id != null">id = #{record.id,jdbcType=INTEGER},</if><if test="record.name != null">name = #{record.name,jdbcType=VARCHAR},</if></set><if test="_parameter != null"><include refid="Update_By_Example_Where_Clause" /></if></update><update id="updateByExample" parameterType="map"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test4set id = #{record.id,jdbcType=INTEGER},name = #{record.name,jdbcType=VARCHAR}<if test="_parameter != null"><include refid="Update_By_Example_Where_Clause" /></if></update><update id="updateByPrimaryKeySelective" parameterType="com.istioservice2.entity.Test4"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test4<set><if test="name != null">name = #{name,jdbcType=VARCHAR},</if></set>where id = #{id,jdbcType=INTEGER}</update><update id="updateByPrimaryKey" parameterType="com.istioservice2.entity.Test4"><!--WARNING - @mbg.generatedThis element is automatically generated by MyBatis Generator, do not modify.-->update test4set name = #{name,jdbcType=VARCHAR}where id = #{id,jdbcType=INTEGER}</update>
</mapper>

●application.properties

server.port=8082#本地测试用
spring.datasource.url=jdbc:postgresql://2.0.0.1:5432/test1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
#k8s环境用
#spring.datasource.url=jdbc:postgresql://10.108.206.185:5432/test1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driverClassName=org.postgresql.Driver
#mybatis.config-location=classpath:mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis.type-aliases-package=com.istioservice2.entity

●file.conf

transport {# tcp udt unix-domain-sockettype = "TCP"#NIO NATIVEserver = "NIO"#enable heartbeatheartbeat = true# the client batch send request enableenableClientBatchSendRequest = true#thread factory for nettythreadFactory {bossThreadPrefix = "NettyBoss"workerThreadPrefix = "NettyServerNIOWorker"serverExecutorThread-prefix = "NettyServerBizHandler"shareBossWorker = falseclientSelectorThreadPrefix = "NettyClientSelector"clientSelectorThreadSize = 1clientWorkerThreadPrefix = "NettyClientWorkerThread"# netty boss thread size,will not be used for UDTbossThreadSize = 1#auto default pin or 8workerThreadSize = "default"}shutdown {# when destroy server, wait secondswait = 3}serialization = "seata"compressor = "none"
}
service {#transaction service group mappingvgroupMapping.istio_tx_group = "default"#only support when registry.type=file, please don't set multiple addresses#■■■■■■■■■■■■■ seata 地址设置 start ■■■■■■■■■■■■■default.grouplist = "172.22.70.72:8091"#■■■■■■■■■■■■■ seata 地址设置 end ■■■■■■■■■■■■■#degrade, current not supportenableDegrade = false#disable seatadisableGlobalTransaction = false
}client {rm {asyncCommitBufferLimit = 10000lock {retryInterval = 10retryTimes = 30retryPolicyBranchRollbackOnConflict = true}reportRetryCount = 5tableMetaCheckEnable = falsereportSuccessEnable = false}tm {commitRetryCount = 5rollbackRetryCount = 5}undo {dataValidation = truelogSerialization = "jackson"logTable = "undo_log"}log {exceptionRate = 100}
}

●log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO"><!-- ■■■■■ 要使这个配置生效,需要pom中排除掉spring-boot-starter-logging ■■■■■ --><!--全局参数--><Properties><!--%d{yyyy-MM-dd HH:mm:ss.SSS} =>格式化时间 2020-01-21 14:03:53.858%5p                         =>输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL%t                          =>输出产生该日志事件的线程名%c{1}                       =>输出日志信息所属的类目,通常就是所在类的全名%L                          =>输出代码中的行号%m                          =>输出代码中指定的消息,产生的日志具体信息%n                          =>输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"输出日志信息换行--><Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %t %c{1}:%L - %m%n</Property><!-- ■■■日志输出文件夹【不同项目在同一个目录下时,用日志文件夹区分不同项目日志】 --><Property name="logDir">service2Logs/</Property></Properties><Loggers><Root level="INFO"><AppenderRef ref="console"/><AppenderRef ref="asyncInfoLog"/><AppenderRef ref="asyncLogError"/></Root></Loggers><Appenders><!-- 定义输出到控制台 --><Console name="console" target="SYSTEM_OUT" follow="true"><!--控制台只输出level及以上级别的信息--><ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/><PatternLayout><Pattern>${pattern}</Pattern></PatternLayout></Console><!-- 同一来源的Appender可以定义多个RollingFile,定义按天存储日志 --><!-- INFO日志 --><RollingFile name="rolling_file_info" fileName="${logDir}/info_service2.log"filePattern="${logDir}/info_service2_%d{yyyy-MM-dd}.log"><Filters><ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/><ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/></Filters><PatternLayout><Pattern>${pattern}</Pattern></PatternLayout><Policies><TimeBasedTriggeringPolicy interval="1"/></Policies><!-- 日志保留策略,配置只保留180天 --><DefaultRolloverStrategy><Delete basePath="${logDir}/" maxDepth="1"><IfFileName glob="info_service2_*.log"/><IfLastModified age="180d"/></Delete></DefaultRolloverStrategy></RollingFile><!-- ERROR日志 --><RollingFile name="rolling_file_error" fileName="${logDir}/error_service2.log"filePattern="${logDir}/error_service2_%d{yyyy-MM-dd}.log"><Filters><ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="NEUTRAL"/><ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/></Filters><PatternLayout><Pattern>${pattern}</Pattern></PatternLayout><Policies><TimeBasedTriggeringPolicy interval="1"/></Policies><!-- 日志保留策略,配置只保留180天 --><DefaultRolloverStrategy><Delete basePath="${logDir}/" maxDepth="1"><IfFileName glob="error_service2_*.log"/><IfLastModified age="180d"/></Delete></DefaultRolloverStrategy></RollingFile><Async name="asyncInfoLog" includeLocation="true"><AppenderRef ref="rolling_file_info"/></Async><Async name="asyncLogError" includeLocation="true"><AppenderRef ref="rolling_file_error"/></Async></Appenders>
</Configuration>

●registry.conf

registry {# file 、nacos 、eureka、redis、zk、consul、etcd3、sofatype = "file"loadBalance = "RandomLoadBalance"loadBalanceVirtualNodes = 10nacos {application = "seata-server"serverAddr = "127.0.0.1:8848"group = "SEATA_GROUP"namespace = ""cluster = "default"username = ""password = ""}eureka {serviceUrl = "http://localhost:8761/eureka"application = "default"weight = "1"}redis {serverAddr = "localhost:6379"db = 0password = ""cluster = "default"timeout = 0}zk {cluster = "default"serverAddr = "127.0.0.1:2181"sessionTimeout = 6000connectTimeout = 2000username = ""password = ""}consul {cluster = "default"serverAddr = "127.0.0.1:8500"}etcd3 {cluster = "default"serverAddr = "http://localhost:2379"}sofa {serverAddr = "127.0.0.1:9603"application = "default"region = "DEFAULT_ZONE"datacenter = "DefaultDataCenter"cluster = "default"group = "SEATA_GROUP"addressWaitTime = "3000"}file {name = "file.conf"}
}config {# file、nacos 、apollo、zk、consul、etcd3type = "file"nacos {serverAddr = "127.0.0.1:8848"namespace = ""group = "SEATA_GROUP"username = ""password = ""}consul {serverAddr = "127.0.0.1:8500"}apollo {appId = "seata-server"apolloMeta = "http://192.168.1.204:8801"namespace = "application"apolloAccesskeySecret = ""}zk {serverAddr = "127.0.0.1:2181"sessionTimeout = 6000connectTimeout = 2000username = ""password = ""}etcd3 {serverAddr = "http://localhost:2379"}file {name = "file.conf"}
}

●pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns=".0.0" xmlns:xsi=""xsi:schemaLocation=".0.0 .0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.2</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com</groupId><artifactId>istio-service2</artifactId><version>1.0</version><name>istio-service2</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.0.0</version></dependency><!-- 分布式事务 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><version>2.2.6.RELEASE</version><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>1.4.1</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion></exclusions></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

以上为Java项目部分。

以下为istio配置内容。

首先配置一个本项目的命名空间(istio-work-ns)

#创建命名空间
kubectl create ns istio-work-ns

将此命名空间设置为isito管理的命名空间(在此命名空间内创建的pod会自动配置sidecar)

#给命名空间打标签
kubectl label namespace istio-work-ns istio-injection=enabled

下面将3个服务打docker镜像,并可让k8s集群的3台机器都能访问到这个镜像。可以采用docker仓库的方式,也可以在一台机器上打镜像然后导出到其它机器上。

#制作docker镜像
docker build -t istio/service1:1.0 -f ./istioService1Dockerfile .#导出镜像
docker save -o istioservice1.tar istio/service1:1.0#导入镜像(集群中各个节点都要导入需部署镜像)
docker load < ./istioservice1.tar

以下是3个项目打docker镜像的配置文件

●istioClientDockerfile

#指定以openjdk:8-jre 为基础镜像,来构建此镜像,可以理解为运行的需要基础环境
FROM openjdk:8-jre
#WORKDIR指令用于指定容器的一个目录, 容器启动时执行的命令会在该目录下执行。
WORKDIR /
#将当前client.jar 复制到容器根目录下
ADD istio-client-1.0.jar istio-client-1.0.jar
#将依赖包 复制到容器根目录/libs下
#ADD libs /libs
#暴露容器端口为50051 Docker镜像告知Docker宿主机应用监听了50051端口
EXPOSE 8080
#容器启动时执行的命令
ENTRYPOINT ["java","-jar","/istio-client-1.0.jar"]

●istioService1Dockerfile
 

#指定以openjdk:8-jre 为基础镜像,来构建此镜像,可以理解为运行的需要基础环境
FROM openjdk:8-jre
#WORKDIR指令用于指定容器的一个目录, 容器启动时执行的命令会在该目录下执行。
WORKDIR /
#将当前client.jar 复制到容器根目录下
ADD istio-service1-1.0.jar istio-service1-1.0.jar
#将依赖包 复制到容器根目录/libs下
#ADD libs /libs
#暴露容器端口为50051 Docker镜像告知Docker宿主机应用监听了50051端口
EXPOSE 8081
#容器启动时执行的命令
ENTRYPOINT ["java","-jar","/istio-service1-1.0.jar"]

●istioService2Dockerfile

#指定以openjdk:8-jre 为基础镜像,来构建此镜像,可以理解为运行的需要基础环境
FROM openjdk:8-jre
#WORKDIR指令用于指定容器的一个目录, 容器启动时执行的命令会在该目录下执行。
WORKDIR /
#将当前client.jar 复制到容器根目录下
ADD istio-service2-1.0.jar istio-service2-1.0.jar
#将依赖包 复制到容器根目录/libs下
#ADD libs /libs
#暴露容器端口为50051 Docker镜像告知Docker宿主机应用监听了50051端口
EXPOSE 8082
#容器启动时执行的命令
ENTRYPOINT ["java","-jar","/istio-service2-1.0.jar"]

以下是3个项目的pod和service配置

●client.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: istioclientnamespace: istio-work-nslabels:app: istioclient
spec:replicas: 1selector:matchLabels:app: istioclienttemplate:metadata:labels:app: istioclientspec:containers:- name: istioclientimage: istio/client:1.0imagePullPolicy: IfNotPresentports:- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:name: istioclientnamespace: istio-work-ns
spec:clusterIP: 10.108.232.10ports:- port: 8080targetPort: 8080selector:app: istioclient

●service1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: istioservice1namespace: istio-work-nslabels:app: istioservice1
spec:replicas: 1selector:matchLabels:app: istioservice1template:metadata:labels:app: istioservice1spec:containers:- name: istioservice1image: istio/service1:1.0imagePullPolicy: IfNotPresentports:- containerPort: 8081
---
apiVersion: v1
kind: Service
metadata:name: istioservice1namespace: istio-work-ns
spec:clusterIP: 10.108.232.20ports:- port: 8081targetPort: 8081selector:app: istioservice1

●service2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: istioservice2namespace: istio-work-nslabels:app: istioservice2
spec:replicas: 1selector:matchLabels:app: istioservice2template:metadata:labels:app: istioservice2spec:containers:- name: istioservice2image: istio/service2:1.0imagePullPolicy: IfNotPresentports:- containerPort: 8082
---
apiVersion: v1
kind: Service
metadata:name: istioservice2namespace: istio-work-ns
spec:clusterIP: 10.108.232.30ports:- port: 8082targetPort: 8082selector:app: istioservice2

配置本项目的入口(istio的ingress gateway)

●gateway-test.yaml

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:name: alp-gatewaynamespace: istio-work-ns
spec:selector:istio: ingressgateway # use istio default controllerservers:- port:number: 80name: httpprotocol: HTTPhosts:- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: alp-vsnamespace: istio-work-ns
spec:hosts:- "*"gateways:- alp-gatewayhttp:- match:- uri:prefix: /testroute:- destination:host: istioclientport:number: 8080

查看ingress gateway的80端口的映射地址

kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                                                                                                      AGE
istio-ingressgateway   LoadBalancer   10.103.204.76   <pending>     15020:31965/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:31388/TCP,15030:31011/TCP,15031:30711/TCP,15032:30715/TCP,15443:32497/TCP   4d2h

 确认服务部署成功。访问地址:http://192.168.42.131:31380/test/getTest1

以上为采用istio的ingress gateway方式开放服务。
还可以采用k8s的ingress方式开放服务。
●ingress.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:name: ingress-demonamespace: istio-work-ns
spec:rules:- host: k8s.testhttp:paths:- path: /backend:serviceName: istioclientservicePort: 8080

访问此服务需要在本地hosts文件中追加k8s.test配置

C:\Windows\System32\drivers\etc\hosts

192.168.42.131 k8s.test

访问地址/test/getTest1,确认项目发布成功。

更多推荐

docker+k8s+istio项目实例

本文发布于:2024-03-09 22:58:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1726374.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:实例   项目   docker   k8s   istio

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!