istio: h5应用访问后端接口 (跨域+路由管理)

本文实验链路:h5 > demo-a > demo-b
在实验过程出现跨域问题,直接使用istio解决,没有调整后端代码

h5应用版本准备

版本代码区分

实验需要h5项目有两个版本,为了区分,在istioDemo页面最显眼的位置显示不同的文字。
v1版本:
在这里插入图片描述

latest版本:
在这里插入图片描述

打包docker镜像

打包方法参考 docker: 打包h5项目的镜像
本文打了两个版本的镜像,如下:
在这里插入图片描述

部署h5应用

应用部署到命名空间:istio-demos
关于命名空间的创建以及添加istio-injection标签参考istio gateway入口流量路由管控#二、应用部署

创建Service和Deployment

创建yaml文件: demo-h5-vault.yaml

apiVersion: v1
kind: Service
metadata:
  name: demo-istio-h5
  labels:
    app: demo-istio-h5
    service: demo-istio-h5
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
  selector:
    app: demo-istio-h5
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-istio-h5-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo-istio-h5
      version: v1
  template:
    metadata:
      labels:
        app: demo-istio-h5
        version: v1
    spec:
      serviceAccountName: istio-demo    
      containers:
      - image: demo-istio-h5:v1.0
        imagePullPolicy: IfNotPresent
        name: demo-istio-h5
        ports:
        - containerPort: 80

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-istio-h5-latest
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo-istio-h5
      version: latest
  template:
    metadata:
      labels:
        app: demo-istio-h5
        version: latest
    spec:
      serviceAccountName: istio-demo    
      containers:
      - image: demo-istio-h5:latest
        imagePullPolicy: IfNotPresent
        name: demo-istio-h5
        ports:
        - containerPort: 80

执行kubectl命令创建service和deployment

kubectl apply -f demo-h5-vault.yaml -n istio-demos

h5 路由管理

创建定义istio Gateway和VirtualService的yaml文件:demo-h5-gateway-multiversion.yaml

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: demo-istio-h5-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "demoh5.istiodemos.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: demo-istio-h5-dr
spec:
  host: demo-istio-h5
  trafficPolicy:
    loadBalancer:
        simple: LEAST_CONN
  subsets:
  - name: v1
    labels:
      version: v1
    trafficPolicy:
      loadBalancer:
        simple: ROUND_ROBIN
  - name: latest
    labels: 
      version: latest
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: demo-istio-h5-vs
spec:
  hosts:
  - "demoh5.istiodemos.com"
  gateways:
  - demo-istio-h5-gateway
  http:
  - match:
    - queryParams:
        v:
          exact: v1
          # regex: ae\d+$
    route:
    - destination:
        host: demo-istio-h5
        subset: v1
  - route:
    - destination:
        host: demo-istio-h5
        subset: latest

该yaml文件中将v1版本和latest版本做了路由定义,规则如下:

将url参数v=v1时,路由到v1版本的demo-istio-h5
否则都路由到latest版本的demo-istio-h5

创建istio Gateway和VirtualService。

kubectl apply -f demo-h5-gateway-multiversion.yaml -n istio-demos

接下来就可以通过域名 demoh5.istiodemos.com 访问demo-istio-h5应用了,且还会根据参数路由到不同的版本。

关于域名映射的方法可以参考istio gateway入口流量路由管控三、外部访问应用

下面以访问url做示例:
http://demoh5.istiodemos.com/?v=v1#/istioDemo => v1版本
在这里插入图片描述

http://demoh5.istiodemos.com/#/istioDemo => latest版本
在这里插入图片描述

部署后端应用

demo-a和demo-b的部署参考以下两篇文章:
istio gateway入口流量路由管控
istio 访问网格内的服务(路由管理)

istio 解决跨域问题

现在测试通过h5访问后端接口: http://demoa.istiodemos.com/test/request-b?forward=istio-springboot-demo-b&a=av356

访问结果:
在这里插入图片描述
出现跨域问题,调整下VirtualService istio-springboot-demo-a-vs, 添加跨域的策略(corsPolicy),yaml内容在demo-a-gateway-multiversion.yaml

...
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: istio-springboot-demo-a-vs
spec:
  hosts:
  - "*"
  gateways:
  - istio-springboot-demo-a-gateway
  http:
  - match:
    - queryParams:
        a:
          # exact: ad
          regex: av\d+$
    route:
    - destination:
        host: istio-springboot-demo-a
        subset: v1
    corsPolicy:
      allowOrigins:
      - regex: "http://.*"
      allowMethods:
      - POST
      - GET
      allowHeaders:
      - XSRF-TOKEN
      - xsrfHeaderName
      - X-XSRF-TOKEN
      - maxContentLength
      - maxBodyLength
  - route:
    - destination:
        host: istio-springboot-demo-a
        subset: latest
    corsPolicy:
      allowOrigins:
      - regex: "http://.*"
      allowMethods:
      - POST
      - GET
      allowHeaders:
      - XSRF-TOKEN
      - xsrfHeaderName
      - X-XSRF-TOKEN
      - maxContentLength
      - maxBodyLength

执行kubectl apply 命令将调整后的内容生效

kubectl apply -f demo-a-gateway-multiversion.yaml -n istio-demos

再来看看访问结果,跨域问题没有了
在这里插入图片描述

实验结果

路由规则

应用 规则 描述
h5 queryParams.v.exact: v1 url参数v=v1时路由到v1版本,否则都路由到latest版本
demo-a queryParams.a.regex: av\d+$ url参数a匹配正则av\d+$时路由到v1版本,否则路由到latest版本|
demo-b queryParams.a.regex: ae\d+$ url参数a匹配正则ae\d+$时路由到v1版本,否则路由到latest版本|

访问结果

h5应用

请求URL h5版本
http://demoh5.istiodemos.com/?v=v1#/istioDemo v1版本
http://demoh5.istiodemos.com/?v=v1f#/istioDemo latest版本
http://demoh5.istiodemos.com/#/istioDemo latest版本

后端应用

请求url demo-a版本 demo-b版本
http://demoa.istiodemos.com/test/request-b?forward=istio-springboot-demo-b&a=av356 v1版本 latest版本
http://demoa.istiodemos.com/test/request-b?forward=istio-springboot-demo-b&a=ae356 latest版本 v1版本
http://demoa.istiodemos.com/test/request-b?forward=istio-springboot-demo-b&a=a356 latest版本 latest版本

下面是以上三个url返回的内容截图

  • http://demoa.istiodemos.com/test/request-b?forward=istio-springboot-demo-b&a=av356
    在这里插入图片描述

  • http://demoa.istiodemos.com/test/request-b?forward=istio-springboot-demo-b&a=ae356
    在这里插入图片描述

  • http://demoa.istiodemos.com/test/request-b?forward=istio-springboot-demo-b&a=a356
    在这里插入图片描述

小结

通过istio可以非常方便的定义http 入口请求的路由规则和网格内的访问的路由规则,不管是后端API还是h5应用。
但是对于更复杂的路则规则本文并没有去尝试。

附录

h5 istioDemo页面的代码

<template>
  <div>
    <h2> Istio Demo Latest</h2>
    <el-form>
        <el-form-item label="Domain">
            <el-input placeholder="域名" v-model="domain"> </el-input>
        </el-form-item>
        <el-form-item label="Api Path">
            <el-input placeholder="Api Path" v-model="apiPath"></el-input>
        </el-form-item>
        <el-form-item label="Heanders">
            <el-input type="textarea" placeholder="Heanders" v-model="headers" rows="6" cols="6"></el-input>
        </el-form-item>
        <el-form-item label="Parameters">
            <el-input type="textarea" placeholder="Parameters" v-model="params" rows="6" cols="6"></el-input>
        </el-form-item>
        <el-form-item>
            <el-button 
            type="primary" 
            style="width:100%"
            @click="doGoFunc">GO!</el-button>
        </el-form-item>
        <el-form-item label="Response">
            <el-input  type="textarea" placeholder="Response" rows="6" cols="6" v-model="res" readonly></el-input>
        </el-form-item>

    </el-form>
  </div>
</template>

<script>

import axios from 'axios'

export default {
  name: 'IstioDemo',
  data () {
    return {
      domain:"http://demoa.istiodemos.com",
      apiPath:"/test/request-b",
      params:"{\"forward\":\"istio-springboot-demo-b\", \"a\":\"av356\"}",
      headers:"{}",
      res:""
    }
  },created(){
		this.init()
	},methods:{
		init(){//获取数据
      
		},
    doGoFunc(){
      var parameters = JSON.parse(this.params)
      var headers = JSON.parse(this.headers)

      axios({
              url: this.domain + this.apiPath,
              method: 'get',
              headers: headers,
              params: parameters
            }).then(res => {
              this.res = "success\n" + res.data;
            }).catch(res=>{
              this.res = "fail\n" + JSON.stringify(res);
            })
    }
  }
}
</script>

参考

https://istio.io/latest/zh/docs/reference/config/networking/virtual-service/#CorsPolicy

猜你喜欢

转载自blog.csdn.net/Mr_rain/article/details/126045383