当前位置: 首页 > news >正文

网站规划有前途吗5173网站源码

网站规划有前途吗,5173网站源码,wordpress 更新版本,网站建设估价基础介绍 1、Istio的定义 Istio 是一个开源服务网格#xff0c;它透明地分层到现有的分布式应用程序上。 Istio 强大的特性提供了一种统一和更有效的方式来保护、连接和监视服务。 Istio 是实现负载平衡、服务到服务身份验证和监视的路径——只需要很少或不需要更改服务代码…基础介绍 1、Istio的定义 Istio 是一个开源服务网格它透明地分层到现有的分布式应用程序上。 Istio 强大的特性提供了一种统一和更有效的方式来保护、连接和监视服务。 Istio 是实现负载平衡、服务到服务身份验证和监视的路径——只需要很少或不需要更改服务代码。它强大的控制平面带来了重要的特点包括 使用 TLS 加密、强身份认证和授权的集群内服务到服务的安全通信 自动负载均衡的 HTTP, gRPC, WebSocket和 TCP 流量 通过丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制 一个可插入的策略层和配置 API支持访问控制、速率限制和配额 对集群内的所有流量(包括集群入口和出口)进行自动度量、日志和跟踪 官网地址https://istio.io/latest/zh/about/service-mesh/ 使用 Istio 前 使用 Istio 后 2、架构 Istio 服务网格从逻辑上分为数据平面和控制平面。 数据平面 由一组智能代理Envoy组成被部署为 Sidecar。这些代理负责协调和控制微服务之间的所有网络通信。 它们还收集和报告所有网格流量的遥测数据。 控制平面 管理并配置代理来进行流量路由。 https://istio.io/latest/zh/docs/ops/deployment/architecture/ 下图展示了组成每个平面的不同组件 3、Istio安装 3.1 下载Istio 1下载指定版本 https://istio.io/latest/zh/docs/setup/getting-started/#download # 指定版本下载 # 要为 x86_64 架构下载 Istio 1.20.0请运行 curl -L https://istio.io/downloadIstio | ISTIO_VERSION1.20.0 TARGET_ARCHx86_64 sh -如果下载不了去https://github.com/istio/istio/releases/tag/1.20.0下载 wget https://github.com/istio/istio/releases/download/1.20.0/istio-1.20.0-linux-amd64.tar.gz 2解压后进入安装目录 tar -zxvf istio-1.20.0-linux-amd64.tar.gz 安装目录包含 bin: 存放istioctl二进制文件manifests: istio 的内置chart目录默认使用这些内置 chart 生成安装清单安装过程也可以自行设置–manifestsother_manifests/参数来指定外部 chartsamples: istio 提供的一些示例应用程序tools: 一些工具如certs用于生成证书 3为了方便使用istioctl将bin目录添加到我们的环境变量中 export PATH$PWD/bin:$PATH加入/etc/profile永久生效 [rootk8s-master01 istio-1.20.0]# vim /etc/profile export PATH/root/istio-1.20.0/bin:$PATH [rootk8s-master01 istio-1.20.0]# source /etc/profile3.2 执行安装 ## istio提供的几种内置配置这些配置文件提供了对 Istio 控制平面和 Istio 数据平面 Sidecar 的定制内容。 [rootmaster istio-1.15.3]# istioctl profile list Istio configuration profiles:defaultdemoemptyexternalminimalopenshiftpreview1、default根据IstioOperatorAPI 的默认设置启动组件。 建议用于生产部署和 Multicluster Mesh中的 Primary Cluster。您可以运行istioctl profile dump命令来查看默认设置。 2、demo这一配置具有适度的资源需求旨在展示 Istio 的功能。 它适合运行 Bookinfo应用程序和相关任务。此配置文件启用了高级别的追踪和访问日志因此不适合进行性能测试。 3、minimal与默认配置文件相同但只安装了控制平面组件。 它允许您使用 Separate Profile配置控制平面和数据平面组件(例如 Gateway)。 4、remote配置 Multicluster Mesh的 Remote Cluster。 5、empty不部署任何东西。可以作为自定义配置的基本配置文件。 6、preview预览文件包含的功能都是实验性。这是为了探索 Istio 的新功能。不确保稳定性、安全性和性能使用风险需自负。 标注✔的组件安装在每个配置文件中 # 查看demo配置 istioctl profile dump demo对于本次安装我们采用demo配置组合。 选择它是因为它包含了一组专为测试准备的功能集合另外还有用于生产或性能测试的配置组合。 $ istioctl install --set profiledemo -y ✔ Istio core installed ✔ Istiod installed ✔ Egress gateways installed ✔ Ingress gateways installed ✔ Installation complete给命名空间添加标签指示 Istio 在部署应用的时候自动注入 Envoy 边车代理 $ kubectl label namespace default istio-injectionenabled namespace/default labeled4.部署Bookinfo示例应用 官网https://istio.io/latest/zh/docs/examples/bookinfo/ Bookinfo应用模仿在线书店的一个分类显示一本书的信息。 页面上会显示一本书的描述书籍的细节ISBN、页数等以及关于这本书的一些评论。 Bookinfo 应用分为四个单独的微服务 productpage这个微服务会调用details和reviews两个微服务用来生成页面。details这个微服务中包含了书籍的信息。reviews这个微服务中包含了书籍相关的评论。它还会调用ratings微服务。ratings这个微服务中包含了由书籍评价组成的评级信息。 reviews微服务有 3 个版本 v1 版本不会调用ratings服务。v2 版本会调用ratings服务并使用 1 到 5 个黑色星形图标来显示评分信息。v3 版本会调用ratings服务并使用 1 到 5 个红色星形图标来显示评分信息。 下图展示了这个应用的端到端架构 4.1 启动应用服务 1进入 Istio 安装目录。 2Istio 默认自动注入 Sidecar. 请为default命名空间打上标签istio-injectionenabled $ kubectl label namespace default istio-injectionenabled3使用 kubectl 部署应用 $ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml上面的命令会启动全部的四个服务其中也包括了 reviews 服务的三个版本v1、v2 以及 v3。 4确认所有的服务和 Pod 都已经正确的定义和启动 $ kubectl get servicesNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE details ClusterIP 10.0.0.31 none 9080/TCP 6m kubernetes ClusterIP 10.0.0.1 none 443/TCP 7d productpage ClusterIP 10.0.0.120 none 9080/TCP 6m ratings ClusterIP 10.0.0.15 none 9080/TCP 6m reviews ClusterIP 10.0.0.170 none 9080/TCP 6m还有 $ kubectl get podsNAME READY STATUS RESTARTS AGE details-v1-1520924117-48z17 2/2 Running 0 6m productpage-v1-560495357-jk1lz 2/2 Running 0 6m ratings-v1-734492171-rnr5l 2/2 Running 0 6m reviews-v1-874083890-f0qf0 2/2 Running 0 6m reviews-v2-1343845940-b34q5 2/2 Running 0 6m reviews-v3-1813607990-8ch52 2/2 Running 0 6m5要确认 Bookinfo 应用是否正在运行请在某个 Pod 中用curl命令对应用发送请求例如ratings $ kubectl exec $(kubectl get pod -l appratings -o jsonpath{.items[0].metadata.name}) -c ratings -- curl -sS productpage:9080/productpage | grep -o title.*/titletitleSimple Bookstore App/title4.2 确定 Ingress 的 IP 和端口 现在 Bookinfo 服务启动并运行中您需要使应用程序可以从外部访问 Kubernetes 集群 例如使用浏览器。可以使用网关实现这个目标。 1为 Bookinfo 应用程序定义一个网关 使用以下命令创建Istio Gateway $ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yamlgateway.networking.istio.io/bookinfo-gateway created virtualservice.networking.istio.io/bookinfo created确认网关创建完成 $ kubectl get gatewayNAME AGE bookinfo-gateway 32s2设置GATEWAY_URL $ export GATEWAY_URL$INGRESS_HOST:$INGRESS_PORT4.3 确认可以从集群外部访问应用 可以用curl命令来确认是否能够从集群外部访问 Bookinfo 应用程序 $ curl -s http://${GATEWAY_URL}/productpage | grep -o title.*/titletitleSimple Bookstore App/title还可以用浏览器打开网址http://$GATEWAY_URL/productpage来浏览应用的 Web 页面。 如果刷新几次应用的页面就会看到productpage页面中会随机展示reviews服务的不同版本的效果 红色、黑色的星形或者没有显示。reviews服务出现这种情况是因为我们还没有使用 Istio 来控制版本的路由。 4.4 定义服务版本 在可以使用 Istio 控制 Bookinfo 版本路由之前您需要定义可用的版本。 Istio 在目标规则中使用subsets定义服务的版本。运行以下命令为 Bookinfo 服务创建默认的目标规则 $ kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml等待几秒钟以使目标规则生效。 您可以使用以下命令查看目标规则 $ kubectl get destinationrules -o yaml4.5 清理 结束对 Bookinfo 示例应用的体验之后就可以使用下面的命令来完成应用的删除和清理了 $ samples/bookinfo/platform/kube/cleanup.sh流量管理 1、Gateway 在安装 Istio 的时候安装了入口和出口网关。这两个网关实际都运行了一个 Envoy 代理实例它们在网格的边缘作为负载均衡器运行。入口网关接收入站连接而出口网关接收从集群出去的连接。 使用入口网关我们可以对进入集群的流量应用路由规则。 我们可以有一个指向入口网关的单一外部 IP 地址并根据Header将流量路由到集群内的不同服务。 使用 Gateway 资源来配置网关。 下面是一个网关资源的例子 apiVersion: networking.istio.io/v1alpha3kind: Gatewaymetadata:name: my-gatewaynamespace: defaultspec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- dev.example.com- test.example.com网关资源描述了负载均衡器的暴露端口、协议、SNI配置等。 GateWay字段名称、字段含义 metadata.name Gateway 名称 metadata.namespace Gateway 命名空间 spec.selector Gateway 使用填写的标签键值对匹配配置下发的边缘代理网关实例 spec.servers.port.number 端口 spec.servers.port.protocol 通信协议支持HTTP, HTTPS, GRPC, HTTP2, MONGO, TCP, TLS请注意同一网关同一端口的协议配置需要保持一致。 spec.servers.port.name 端口名称 spec.severs.hosts 域名支持通配符 * spec.servers.tls.httpsRedirect 值为 true 时边缘代理网关会对所有 http 请求返回 301 重定向要求客户端发起 https 请求 spec.servers.tls.mode 配置当前端口的 TLS 安全认证模式如需要开启当前端口的安全认证则需要填写。支持PASSTHROUGH, SIMPLE, MUTUAL, AUTO_PASSTHROUGH, ISTIO_MUTUAL spec.servers.tls.credentialName 配置发现 TLS 证书密钥的 secret 的名称 spec.servers.tls.serverCertificate 设置端口的 TLS 证书密钥通过 file mount 形式不推荐推荐采用填写 credentialName 字段加载证书私钥挂载时需要填写的证书路径字段Istio 默认使用网关所在命名空间下 istio-ingressgateway-certs secret 加载证书至路径 /etc/istio/ingressgateway-certs spec.servers.tls.privateKey 设置端口的 TLS 证书密钥通过 file mount 形式不推荐推荐采用填写 credentialName 字段加载证书私钥挂载时需要填写的私钥路径字段Istio 默认使用网关所在命名空间下 istio-ingressgateway-certs secret 加载私钥至路径 /etc/istio/ingressgateway-certs spec.servers.tls.caCertificates 设置端口的 TLS 证书密钥通过 file mount 形式不推荐推荐采用填写 credentialName 字段加载证书私钥挂载时需要填写的跟证书路径字段Istio 默认使用网关所在命名空间下 istio-ingressgateway-ca-certs 加载根证书至路径 /etc/istio/ingressgateway-ca-certs双向认证时需要配置根证书 SNI即服务器名称指示是TLS协议的扩展。它指示在“握手”过程开始时浏览器正在联系哪个主机名允许服务器为多个站点安全地托管多个SSL证书多个网站存在于同一IP地址上。 上述配置文件的解释 配置了一个代理作为负载均衡器为入口暴露80端口配置应用于istio入口网关代理hosts字段作为一个过滤器只有以dev.example.com和test.example.com为目的地的流量会被允许通过。 为了控制和转发流量到集群内运行的实际 Kubernetes 服务我们必须用特定的主机名例如dev.example.com和test.example.com配置一个VirtualService然后将网关连接到它。 1.1 简单路由实例 部署一个tomcat并通过istio网关进行访问。 tomcatdeploy.yaml apiVersion: apps/v1 kind: Deployment metadata:creationTimestamp: nulllabels:app: tomcatname: tomcatnamespace: microservice spec:replicas: 1selector:matchLabels:app: tomcatstrategy: {}template:metadata:creationTimestamp: nulllabels:app: tomcatspec:containers:- image: hub.c.163.com/library/tomcat:latestimagePullPolicy: IfNotPresentname: tomcatports:- containerPort: 8080resources: {}创建一个tomcat servicetomcatsvc.yaml apiVersion: v1 kind: Service metadata:creationTimestamp: nulllabels:app: tomcatname: tomcatnamespace: microservice spec:ports:- port: 80name: tcpprotocol: TCPtargetPort: 8080selector:app: tomcat status:loadBalancer: {}部署一个Gateway资源 ingressgateway80.yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata:name: ingressgateway80 spec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- *这设置*可以使用ip地址来访问入口网关如果配置为具体域名需要修改hosts文件真实域名需要修改A记录 现在还没有绑定VirtualService所以网关还不知道将流量路由到哪里为tomcat服务创建一个 VirtualService并将其绑定到 Gateway 资源上 tomcat-virtualservice.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:name: tomcat-virtualservice spec:hosts:- * gateways: #把VirtualService绑定到ingressgateway80这个网关- ingressgateway80http:- route: #表示路由到tomcat这个servicemicroservice表示命名空间- destination:host: tomcat.microservice.svc.cluster.localport:number: 80访问curl -v 网关外部ip:80 注意其中的header其中有一个serveristio-envoy这表明请求经过了envoy代理 2、VirtualService详解 使用 VirtualService 资源在 Istio 服务网格中进行流量路由。通过 VirtualService我们可以定义流量路由规则并在客户端试图连接到服务时应用这些规则。 具体的配置含义 VirtualService字段名称、字段说明 spec.hosts 定义路由规则关联一组的 hosts可以是带有通配符的 DNS 名称或者 IP 地址IP 地址仅能应用于来源流量为边缘代理网关。该字段能应用于 HTTP 和 TCP 流量。在 Kubernetes 环境中可以使用 service 的名称作为缩写Istio 会按照 VirtualService所在 namespace 补齐缩写例如在 default namespace 的 VirtualService 包含 host 缩写 reviews 会被补齐为 reviews.default.svc.cluster.local。为避免误配置推荐填写 host 全称 spec.gateways 定义应用路由规则的来源流量可以是一个或多个网关或网格内部的 sidecar指定方式为/保留字段 mesh 表示网格内部所有的 sidecar当该参数缺省时会默认填写 mesh即该路由规则的来源流量为网格内部所有 sidecar spec.http 定义一组有序的优先匹配靠前的路由规则应用于 HTTP 流量的路由规则HTTP 路由规则会应用于网格内部的 service 端口命名为 http-, http2-, grpc- 开头的流量以及来自 gateway 的协议为 HTTP, HTTP2, GRPC, TLS-Terminated-HTTPS 的流量 spec.http.match 定义路由的匹配规则列表单个匹配规则项内所有条件是且关系列表中多个匹配规则之间为或关系 spec.http.route 定义路由转发目的地列表一条 HTTP 路由可以是重定向或转发默认转发的目的地可以是一个或多个服务服务版本。同时也可以配置权重、header 操作等行为 spec.http.redirect 定义路由重定向一条 HTTP 路由可以是重定向或转发默认如规则中指定了 passthrough 选项route、redirect 均会被忽略。可将 HTTP 301 重定向到另外的 URL 或 Authority spec.http.rewrite 定义重写 HTTP URL 或 Authority headers不能与重定向同时配置重写操作会在转发前执行 spec.http.timeout 定义 HTTP 请求的超时时间 spec.http.retries 定义 HTTP 请求的重试策略 spec.http.fault 定义 HTTP 流量的故障注入策略开启时超时和重试策略不会开启 spec.http.mirror 定义将 HTTP 流量复制到另一个指定的目的端被复制的流量按照“best effort”原则sidecar/网关不会等待复制流量的响应结果就会从源目的端返回响应。镜像流量的目的服务端会产生监控指标。 spec.http.mirrorPercent 定义流量镜像的复制百分比缺省时复制100%的流量。最大值为100 spec.http.corsPolicy 定义 CORS 策略跨域资源共享Cross-Origin Resource SharingCORS spec.http.headers 定义 header 操作规则包括 request 和 response header 的更新增加移除操作 spec.tcp 定义一组有序的优先匹配靠前的路由规则应用于 TCP 流量的路由规则该路由规则会应用于任何非 HTTP 和 TLS 的端口 spec.tcp.match 定义 TCP 流量路由的匹配规则列表单个匹配规则项内所有条件是且关系列表中多个匹配规则之间为或关系 spec.tcp.route 定义 TCP 连接转发的目的端 spec.tls 定义一组有序的优先匹配靠前的路由规则应用于未终止的 TLS 或 HTTPS 流量的路由规则该路由规则会应用于网格内部的 service 端口命名为 https-tls- 开头的流量来自 gateway 的端口协议为 HTTPS, TLS 的未终止加密流量Service Entry 使用 HTTPS, TLS 协议的端口。当 https-, tls- 端口未关联 VirtualService 规则时将会被视为 TCP 流量 spec.tls.match 定义 TLS 流量路由的匹配规则列表单个匹配规则项内所有条件是且关系列表中多个匹配规则之间为或关系 spec.tls.route 定义连接转发的目的端 2.1 route详解 HTTPRoute规则的功能是满足HTTPMatchRequest条件的流量都被路由到HTTPRouteDestination执行重定向HTTPRedirect、重写HTTPRewrite、重试HTTPRetry、故障注入HTTPFaultInjection、跨站CorsPolicy策略等。HTTPRoute不仅可以做路由匹配还可以做一些写操作来修改请求本身。 2.2 match match是进行路由的匹配条件。 其支持以下一些字段的定义 uri、scheme、method、authority这四个字段都是StringMatch类型匹配请求时都支持exact、prefix和regex三种模式的匹配。 - match:# 代表匹配uri以advertisment开头的请求- uri:prefix: /advertismentheaders匹配请求中的Header是一个map类型。map的key是字符串类型value是StringMatch类型。即对于每一个Header的值都可以使用精确、前缀和正则三种方式进行匹配。 - match: # 匹配header key为source value为north- headers:source:exact: northport表示请求服务的端口。大部分服务只开放一个端口这也是在微服务中推荐的做法在这种场景下可以不指定portsourceLabels是一个map类型的键值对表示请求来源负载匹配标签。这在很多情况有用可以对一组服务都打一个相同的标签然后使用sourceLabels字段对这些服务实施相同的流量规则。在Kubernetes平台上这里的Label就是Pod上的标签。 http: - match: - sourceLabels:app: testAversion: v2gateway表示规则应用的Gateway名称语义同VirtualService 上面的gateway定义是一个更细的Match条件会覆盖在VirtualService上配置的gateway。 在VirtualService中match字段都是数组类型。HTTPMatchRequest中的诸多属性如uri、header、method等都是“与”逻辑而数组中几个元素间关系是“或”逻辑。 例子 - match:- heraders:source:exact: northuri:prefix: /advertisment- uri:prefix: /forecastmatch包含两个HTTPMatchRequest元素其条件的语义是headers中的source取值为“north”且uri以“/advertisment”开头的请求或者uri以“/forecast”开头的请求。 2.3 路由目标(RouteDestination) route字段是一个HTTPRouteDestination类型的数组表示满足条件的流量目标。 在HTTPRouteDestination中主要有三个字段destination请求目标、weight权重、和headersHTTP头操作destination是必选字段。 destination: 这个字段是一个Destination类型结构通过host、subset和port三个属性来描述。表示最终将流量路由到此目标。host是Destination必选字段表示在Istio中注册的服务名建议写全域名。subset表示在host上定义的一个子集。例如在灰度发布中将版本定义为subset配置路由策略会将流量转发到不同版本的subset上。 ..... spec:hosts:- forecasthttp:- route:- destination:host: forecastsubset: v2- destination:host: forecastsubset: v1weight: 表示流量分配的比例在一个route下多个destination的weight总和要求是100。默认100必填字段。示例从原有的v1版本中切分20%的流量到v2版本这也是灰度发布常用的一个流量策略即不区分内容平等的从总流量中切出一部分流量给新版本。 ..... spec:hosts:- forecasthttp:- route:- destination:host: forecastsubset: v2weight: 20- destination:host: forecastsubset: v1weight: 80headers提供了对HTTP header的一种操作机制可以修改一次HTTP请求中的Request或Response的值包含request和response两个字段。request表示在发请求给目标地址时修改Request的header。response表示在返回应答时修改Response的header 对应的类型都是HeaderOperations类型使用set、add、remove字段来定义对Header的操作。set使用map上的key和value覆盖Request和Response中对应的Headeradd追加map上的key和value到原有的Headerremove删除在列表中华指定的Header 2.4 HTTP重定向HTTPRedirect Istio对于HTTP除了做流量路由还可以做适当的其他操作很多原来需要在代码中进行的HTTP操作在使用Istio后通过这些配置都可以达到同样的效果。 通过HTTPRedirect可以发送一个301重定向的应答给服务调用方简单讲就是从一个URL到另外一个URL的永久重定向。用户输入一个URL通过HTTPRedirect可以将其跳转到另一个URL。比较常见的场景有一个在线网站网址变了通过这样的重定向可以在用户输入老地址时跳转到新地址。比如 用户请求老地址 http://forecast/advertisement服务端返回301重定向新地址 http://new-forecast/recommendation/activity用户请求新地址 http://new-forecast/recommendation/activity得到新地址 HTTPRedirect包括两个重要的字段来表示重定向的目标。uri替换URL中的uri部分authority替换URL中的Authority部分 示例 apiVersion:networking.istio.io/v1alpha3 kind: VirtualService metadata:name: forecastnamespace: weather spec:hosts:- forecasthttp:- match:- uri: prefix: /advertisementredirect:uri: /recommendation/activityauthority: new-forecast对forecast服务所有前缀是/advertisement的请求都会被重定向到new-forecast的/recommendation/activity地址。 2.5 HTTP重写HTTPRewrite 通过HTTP重写可以在将请求转发给目标服务前修改HTTP请求中指定部分的内容不同于重定向用户是可见HTTP重写对用户是不可见的因为是在服务端进行的。 和重定向配置类似重写HTTP也包括uri和authority这两个字段。 uri重写URL中的Path部分authority重写URL中的Authority 和HTTPRedirect规则稍有不同的是HTTPRedirect的uri只能替换全部的PathHTTPRewrite的uri是可以重写前缀的即如果原来匹配条件是前缀匹配则修改后只修改匹配到的前缀。 示例 apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:name: forecastnamespace: weather spec:hosts:- forecasthttp:- match:- uri:prefix: /advertisementrewrite:uri: /recommendation/activityroute:- destination:host: forecast前缀匹配/advertisement的请求其请求uri中的这部分前缀会被/recommendation/activity替换 2.6 HTTP重试HTTPRetry HTTP重试是解决很多请求异常最直接、简单的方法尤其是在工作环境比较复杂的场景下可提高总体的服务质量。 但是重试使用不当也会有问题最糟糕的情况是重试一直不成功反而增加延迟和性能开销。所以根据系统运行环境、服务自身特点配置适当的重试规则显得尤为重要。 HTTPRetry可以定义请求失败时的重试策略重试策略包括重试次数、超时、重试条件等这里分别描述相应的三个字段。 attempts必选字段定义重试的次数perTryTimeout每次重试超时的时间单位可以是ms、s、m和hretryOn进行重试的条件可以是多个条件以逗号分隔 其中重试条件retryOn的取值可以包括以下几种: 5xx在上游服务返回5xx应答码或者在没有返回时重试gateway-error类似于5xx异常只对502、503和504应答码进行重试。connect-failure在链接上游服务失败时重试retriable-4xx在上游服务返回可重试的4xx应答码时执行重试。refused-stream在上游服务使用REFUSED_STREAM错误码重置时执行重试。cancelledgRPC应答的Header中状态码是cancelled时执行重试。deadline-exceeded在gRPC应答的Header中状态码是deadline-exceeded时执行重试internal在gRPC应答的Header中状态码是internal时执行重试resource-exhausted在gRPC应答的Header中状态码是resource-exhausted时执行重试unavailable在gRPC应答的Header中状态码是unavailable时执行重试。 示例 配置了一个重试策略在5xx,connect-failure条件下进行最多5次重试每次重试超时为3秒 apiVersion: networking.istio.io/v1alpha3 kind: VirtualService medata:name: forecastnamespace: weather spec:hosts:- forecasthttp:- route:- destination:host: forecastretries:attempts: 5perTryTimeout: 3sretryOn: 5xx,connect-failure2.7 HTTP流量镜像Mirror HTTP流量镜像指的是将流量转发到原目标地址的同时将流量给另外一个目标地址镜像一份。把生产环境中的实际流量镜像一份到另外一个系统上完全不会对生产系统产生影响这里只是镜像了一份流量数据面代理只需要关注原来转发的流量就可以不用等待镜像目标地址的返回。 apiVersion: networking.istio.io:v1alpha3 kind: VirtualService metadata:name: forecastnamespace: weather spec:hosts:- forecasthttp:- route:- destination:host: forecastsubset: v1mirror:host: forecastsubset: v22.8 HTTP故障注入HTTPFaultInjection HTTPFaultInjection通过delay和abort两个字段设置延时和中止两种故障分别表示Proxy延迟转发HTTP请求和中止HTTP请求。 延迟故障注入HTTPFaultInjection中的延迟故障使用HTTPFaultInjection.Delay 类型描述延时故障表示在发送请求前进行一段延时模拟网络、远端服务负载均衡等各种原因导致的失败主要是如下两个字段 fixedDelay一个必选字段表示延迟时间单位可以是毫秒、秒、分钟和小时要求至少大于1毫秒percentage配置的延迟故障作用在多少的比例的请求上通过这种方式可以只让部分请求发生故障。 示例forecast服务v1版本上的1.5%的请求产生10秒的延时 ...... route: - destination:host: forecastsubset: v1 fault:delay:percenttage:value: 1.5fixedDelay: 10s请求中止故障注入HTTPFaultInjection 使用HTTPFaultInjection.Abort 描述中止故障模拟服务端异常给调用的客户端返回预先定义的错误状态码主要有以下两个字段 httpStatus是一个必选字段表示中止的HTTP状态码percentage配置中止故障作用在多少比例的请求上通过这种方式可以只让部分请求发生故障用法通延迟故障 示例让forecast服务v1版本上1.5%的请求返回“500”代码 ...... route: - destination:host: forecastsubset: v1 fault:abort:percnetage: value: 1.5httpStatus: 5002.9 HTTP跨域资源共享CorsPolicy 当一个资源向该资源所在服务器的不同的域发起请求时就会产生一个跨域的HTTP请求。出于安全考虑浏览器会限制从脚本发起的跨域HTTP请求。通过跨域资源共享CORSCross Origin Resource Sharing机制可允许web应用服务器进行跨域访问控制使跨域数据传递安全进行。在实现上是在HTTP Header中追加一些额外的信息来通知浏览器准许以上访问。 在 VirtualService 中可以对满足条件的请求配置跨域资源共享。有allowOrigin、allowMethods、allowHeader、exposeHeader、maxAge、allowCredentials其实都是被转化为 Access-Control-* 的Header。 如下所示允许源自news.com的GET方法的请求的访问: ...... http: - route:- destination:host: forecastcorsPolicy:allowOrigin:- news.comallowMethods:- GETmaxAge: 2d3、DestinationRule 在讲解virtualService中路由目标对象destination中会包含Service子集的subset字段这个服务子集就是通过DestinationRule定义的。 比如 apiVersion: networking.istio.io/v1alpha3kind: DestinationRulemetadata:name: customers-destinationspec:host: customers.default.svc.cluster.localsubsets:- name: v1labels:version: v1- name: v2labels:version: v2上述定义了两个子集v1和v2同时根据标签来决定哪个Pod需要包含在子集中。 DestinationRule字段名称、字段含义 spec.host 关联 DestinationRule 配置的服务名称可以是自动发现的服务例如 Kubernetes service name或通过 ServiceEntry 声明的 hosts。如填写的服务名无法在上述源中找到则该 DestinationRule 中定义的规则无效 spec.subsets 定义服务的版本subsets版本可通过标签键值对匹配匹配服务中的endpoints。可以在 subsets 级覆盖流量策略配置 spec.trafficPolicy 定义流量策略包括负载均衡、连接池、健康检查、TLS 策略 spec.trafficPolicy.loadBalancer 配置负载均衡算法可配置简单负载均衡算法round robin, least conn, random…一致性哈希会话保持支持按 header namecookieIPquery parameter 哈希地域感知负载均衡算法 spec.trafficPolicy.connectionPool 配置与上游服务的连接量可设置 TCP/HTTP 的连接池 spec.trafficPolicy.outlierDetection 配置从负载均衡池中驱逐不健康的 hosts spec.trafficPolicy.tls 连接上游服务的 client 端 TLS 相关配置与 PeerAuthentication 策略server 端 TLS 模式配置配合使用 spec.trafficPolicy.portLevelSettings 配置端口级别的流量策略端口级别的流量策略会覆盖服务 / subsets 级别的流量策略配置 通过 DestinationRule我们可以定义设置如负载均衡配置、连接池大小、局部异常检测等在路由发生后应用于流量。我们可以在trafficPolicy字段下设置流量策略。以下是这些设置 负载均衡器设置连接池设置局部异常点检测客户端 TLS 设置端口流量策略 3.1 负载均衡器设置 通过负载均衡器设置我们可以控制目的地使用哪种负载均衡算法。 示例 apiVersion: networking.istio.io/v1alpha3kind: DestinationRulemetadata:name: customers-destinationspec:host: customers.default.svc.cluster.localtrafficPolicy:loadBalancer:simple: ROUND_ROBIN #将负载均衡算法设置为轮询方式subsets:- name: v1labels:version: v1- name: v2labels:version: v2simple字段提供的负载均衡算法如下 ROUND_ROBIN:轮询算法如果未指定则默认采用这种算法。 LEAST_CONN:最少连接算法算法实现是从两个随机选择的服务后端选择一个活动请求数较少 的后端实例。 RANDOM:从可用的健康实例中随机选择一个。 PASSTHROUGH:直接转发连接到客户端连接的目标地址即没有做负载均衡。 consistentHash字段一致性hash并根据 HTTP 头、cookies 或其他请求属性提供会话亲和性。 httpHeaderName: 基于Header。 httpCookie: 基于Cookie。 useSourceIp:基于源IP计算哈希值。 minimumRingSize:哈希环上虚拟节点数的最小值节点数越多则负载均衡越精细。 trafficPolicy:loadBalancer:consistentHash:httpCookie:name: locationttl: 4s3.2 连接池配置 可以在 TCP 和 HTTP 层面应用于上游服务的每个主机我们可以用它们来控制连接量 TCP连接池配置 maxConnections:上游服务的所有实例建立的最大连接数默认是 1024属于 TCP层的配置对于 HTTP只用于 HTTP/1.1因为 HTTP/2对每个主机都使用单个连接。connectTimeout:TCP连接超时表示主机网络连接超时可以改善因调用服务变慢导致整个链路变慢的情况。tcpKeepalive:设置TCP keepalives是Istio1.1新支持的配置定期给对端发送一个keepalive的探测包判断连接是否可用。 spec:host: myredissrv.prod.svc.cluster.localtrafficPolicy:connectionPool:tcp:maxConnections: 50connectTimeout: 25mstcpKeepalive:probes: 5time: 3600interval: 60shttp连接池配置 http1MaxPendingRequests: 最大等待 HTTP 请求数默认值是 1024只适用于HTTP/1.1 的服务因为 HTTP/2 协议的请求在到来时会立即复用连接不会在连接池等待。http2MaxRequests:最大请求数默认是1024。只适用于HTTP/2服务因为HTTP/1.1使用最大连接数maxConnections即可表示上游服务的所有实例处理的最大请求数maxRequestsPerConnection:每个连接的最大请求数。HTTP/1.1和HTTP/2连接池都遵循此参数。如果没有设置则没有限制。设置为1时表示每个连接只处理一个请求也就是禁用了Keep-alivemaxRetries:最大重试次数默认是3表示服务可以执行的最大重试次数。如果调用端因为偶尔抖动导致请求直接失败则可能会带来业务损失一般建议配置重试若重试成功则可正常返回数据 只不过比原来响应得慢一点但重试次数太多会影响性能要谨慎使用。idleTimeout:空闲超时定义在多长时间内没有活动请求则关闭连接。 http可以和tcp配置使用示例 spec:host: myredissrv.prod.svc.cluster.localtrafficPolicy:connectionPool:tcp:maxConnections: 80connectTimeout: 25mshttp:http2MaxRequests: 800maxRequestsPerConnection: 10配置最大80个连接只允许最多有800个并发请求每个连接 的请求数不超过10个连接超时是25毫秒。 3.3 异常点检测 异常点检测是一个断路器的实现它跟踪上游服务中每个主机Pod的状态。如果一个主机开始返回 5xx HTTP 错误它就会在预定的时间内被从负载均衡池中弹出。对于 TCP 服务Envoy 将连接超时或失败计算为错误。 两种健康检查 主动型的健康检查定期探测目标服务实例根据应答来判断服务实例的健康状态。如负载均衡器中的健康检查被动型的健康检查通过实际的访问情况来找出不健康的实例如isito中的异常点检查。 异常实例检查相关的配置 consecutiveErrors:实例被驱逐前的连续错误次数默认是 5。对于 HTTP 服务返回 502、503 和 504 的请求会被认为异常;对于 TCP 服务连接超时或者连接错误事件会被认为异常。interval:驱逐的时间间隔默认值为10秒要求大于1毫秒单位可以是时、分、毫秒。baseEjectionTime:最小驱逐时间。一个实例被驱逐的时间等于这个最小驱逐时间乘以驱逐的次数。这样一个因多次异常被驱逐的实例被驱逐的时间会越来越长。默认值为30秒要求大于1毫秒单 位可以是时、分、毫秒。maxEjectionPercent:指负载均衡池中可以被驱逐的故障实例的最大比例默认是10%设置这个值是为了避免太多的服务实例被驱逐导致服务整体能力下降。minHealthPercent:最小健康实例比例是Istio 1.1新增的配置。当负载均衡池中的健康实例数的 例大于这个比例时异常点检查机制可用;当可用实例数的比例小于这个比例时异常点检查功能将被禁用所有服务实例不管被认定为健康还是不健康都可以接收请求。参数的默认值为50%。 下面是一个例子它设置了 500 个并发的 HTTP2 请求http2MaxRequests的限制每个连接不超过 10 个请求maxRequestsPerConnection到该服务。每 5 分钟扫描一次上游主机Podinterval如果其中任何一个主机连续失败 10 次contracticalErrorsEnvoy 会将其弹出 10 分钟baseEjectionTime。 trafficPolicy:connectionPool:http:http2MaxRequests: 500maxRequestsPerConnection: 10outlierDetection:consecutiveErrors: 10interval: 5mbaseEjectionTime: 10m3.4 TLS 设置 包含任何与上游服务连接的 TLS 相关设置。下面是一个使用提供的证书配置 mTLS 的例子: trafficPolicy:tls:mode: MUTUALclientCertificate: /etc/certs/cert.pemprivateKey: /etc/certs/key.pemcaCertificates: /etc/certs/ca.pemmtls : 双向认证,客户机和服务器都通过证书颁发机构彼此验证身份。 由同一个 root ca 生成两套证书即客户端证书和服务端证书。客户端使用 https 访问服务端时双方会交换证书并进行认证认证通过方可通信。 其他支持的 TLS 模式有DISABLE没有 TLS 连接SIMPLE在上游端点发起 TLS 连接以及ISTIO_MUTUAL与MUTUAL类似使用 Istio 的 mTLS 证书。 3.5 端口流量策略 在端口上配置流量策略且端口上流量策略会覆盖全局的流量策略。关于配置方法与TrafficPolicy没有大差别一个关键的差别字段就是port。 示例 trafficPolicy:connectionPool:tcp:maxConnections: 80portLevelSettings:- port:number: 80loadBalancer:simple: LEAST_CONNconnectionPool:tcp:maxConnections: 100- port:number: 8000loadBalancer:simple: ROUND_ROBIN3.6 服务子集 Subset定义服务的子集。 属性 name: Subset的名字为必选字段。通过VirtualService引用的就是这个名字。labels:Subset上的标签通过一组标签定义了属于这个Subset的服务实例。比如最常用的标识服务版本的Version标签。trafficPolicy:应用到这个Subset上的流量策略。 示例 ..... spec:hosts: forecastsubsets:- name: v2labels:version: v2trafficPolicy:connectionPool:tcp:maxConnections: 80 # 给一个特定的Subset配置最大连接数4. 实战 使用权重在不同的服务版本之间路由流量 先部署一个Gateway apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata:name: gateway spec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- *[rootmaster weight]# kubectl apply -f gateway.yaml #将default加入istio中 [rootmaster weight]# kubectl label namespace default istio-injectionenabled部署一个应用deploy和service apiVersion: apps/v1kind: Deploymentmetadata:name: web-frontendlabels:app: web-frontendspec:replicas: 1selector:matchLabels:app: web-frontendtemplate:metadata:labels:app: web-frontendversion: v1spec:containers:- image: web-frontend:1.0.0imagePullPolicy: IfNotPresentname: webports:- containerPort: 8080env:- name: CUSTOMER_SERVICE_URLvalue: http://customers.default.svc.cluster.local ---kind: ServiceapiVersion: v1metadata:name: web-frontendlabels:app: web-frontendspec:selector:app: web-frontendports:- port: 80name: httptargetPort: 8080kubectl apply -f web-frontend.yamlCUSTOMER_SERVICE_URL是说上述的web-frontend服务需要访问一个customers的服务所以我们需要部署一个customer的服务 部署 Customers 服务的 v1版本 apiVersion: apps/v1 kind: Deployment metadata:name: customers-v1labels:app: customersversion: v1 spec:replicas: 1selector:matchLabels:app: customersversion: v1template:metadata:labels:app: customersversion: v1spec:containers:- image: customers:1.0.0imagePullPolicy: IfNotPresentname: svcports:- containerPort: 3000 --- kind: Service apiVersion: v1 metadata:name: customerslabels:app: customers spec:selector:app: customersports:- port: 80name: httptargetPort: 3000kubectl apply -f customers-v1.yaml为web-frontend创建一个 VirtualService并将其绑定到 Gateway 资源上 apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:name: web-frontend spec:hosts:- *gateways:- gatewayhttp:- route:- destination:host: web-frontend.default.svc.cluster.localport:number: 80kubectl apply -f web-frontend-vs.yaml访问gateway 创建 DestinationRule并定义两个子集代表 v1 和 v2 版本 apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata:name: customers spec:host: customers.default.svc.cluster.localsubsets:- name: v1labels:version: v1- name: v2labels:version: v2kubectl apply -f customers-dr.yaml 创建 VirtualService 并在目标中指定 v1子集 apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: customersspec:hosts:- customers.default.svc.cluster.localhttp:- route:- destination:host: customers.default.svc.cluster.localport:number: 80subset: v1每当有请求被发送到 Kubernetes Customers 服务时它将被路由到同一服务的 v1子集 kubectl apply -f customers-vs.yaml部署 v2 版的 Customers 服务 apiVersion: apps/v1kind: Deploymentmetadata:name: customers-v2labels:app: customersversion: v2spec:replicas: 1selector:matchLabels:app: customersversion: v2template:metadata:labels:app: customersversion: v2spec:containers:- image: customers:2.0.0imagePullPolicy: IfNotPresentname: svcports:- containerPort: 3000kubectl apply -f customers-v2.yaml使用weight字段并修改 VirtualService使 50% 的流量被发送到 v1 子集另 50% 发送到 v2 子集 apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:name: customers spec:hosts:- customers.default.svc.cluster.localhttp:- route:- destination:host: customers.default.svc.cluster.localport:number: 80subset: v1weight: 50- destination:host: customers.default.svc.cluster.localport:number: 80subset: v2weight: 50kubectl apply -f customers-50-50.yaml测试刷新页面在v1和v2版本之间切换更改权重 刷新页面观察 使用请求属性在多个服务版本之间路由流量 部署 Gateway apiVersion: networking.istio.io/v1alpha3kind: Gatewaymetadata:name: gatewayspec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- *kubectl apply -f gateway.yaml 部署Web前端、Customers v1、Customers v2以及相应的 VirtualServices 和 DestinationRule。一旦一切部署完毕所有流量将被路由到 Customers v1。apiVersion: apps/v1kind: Deploymentmetadata:name: web-frontendlabels:app: web-frontendspec:replicas: 1selector:matchLabels:app: web-frontendtemplate:metadata:labels:app: web-frontendversion: v1spec:containers:- image: web-frontend:1.0.0imagePullPolicy: IfNotPresentname: webports:- containerPort: 8080env:- name: CUSTOMER_SERVICE_URLvalue: http://customers.default.svc.cluster.local ---kind: ServiceapiVersion: v1metadata:name: web-frontendlabels:app: web-frontendspec:selector:app: web-frontendports:- port: 80name: httptargetPort: 8080 ---apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: web-frontendspec:hosts:- *gateways:- gatewayhttp:- route:- destination:host: web-frontend.default.svc.cluster.localport:number: 80kubectl apply -f web-frontend.yamlapiVersion: apps/v1kind: Deploymentmetadata:name: customers-v1labels:app: customersversion: v1spec:replicas: 1selector:matchLabels:app: customersversion: v1template:metadata:labels:app: customersversion: v1spec:containers:- image: customers:1.0.0imagePullPolicy: IfNotPresentname: svcports:- containerPort: 3000 ---apiVersion: apps/v1kind: Deploymentmetadata:name: customers-v2labels:app: customersversion: v2spec:replicas: 1selector:matchLabels:app: customersversion: v2template:metadata:labels:app: customersversion: v2spec:containers:- image: customers:2.0.0imagePullPolicy: IfNotPresentname: svcports:- containerPort: 3000 ---kind: ServiceapiVersion: v1metadata:name: customerslabels:app: customersspec:selector:app: customersports:- port: 80name: httptargetPort: 3000 ---apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: customersspec:hosts:- customers.default.svc.cluster.localhttp:- route:- destination:host: customers.default.svc.cluster.localport:number: 80subset: v1 ---apiVersion: networking.istio.io/v1alpha3kind: DestinationRulemetadata:name: customersspec:host: customers.default.svc.cluster.localsubsets:- name: v1labels:version: v1- name: v2labels:version: v2kubectl apply -f customers.yaml此时测试流量都来自于v1. 更新VirtualService如果请求中包含一个 headeruser: debug就把流量路由到 Customers v2没有就路由到v1 apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: customersspec:hosts:- customers.default.svc.cluster.localhttp:- match:- headers:user:exact: debugroute:- destination:host: customers.default.svc.cluster.localport:number: 80subset: v2- route:- destination:host: customers.default.svc.cluster.localport:number: 80subset: v1kubectl apply -f customers-vs.yaml测试curl -H “user: debug” http://GATEWAY_URL/ 5、实战观察故障注入 部署 Web 前端和 Customer V1 服务。然后我们将在 Zipkin、Kiali 和 Grafana 中注入故障和延迟并观察它们 部署Gateway apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata:name: ingressgateway80 spec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- *kubectl apply -f ingressgateway80.yaml 部署 Web Frontend、Service 和 VirtualService。 apiVersion: apps/v1 kind: Deployment metadata:name: web-frontendlabels:app: web-frontend spec:replicas: 1selector:matchLabels:app: web-frontendtemplate:metadata:labels:app: web-frontendversion: v1spec:containers:- image: web-frontend:1.0.0imagePullPolicy: Alwaysname: webports:- containerPort: 8080env:- name: CUSTOMER_SERVICE_URLvalue: http://customers.default.svc.cluster.local --- kind: Service apiVersion: v1 metadata:name: web-frontendlabels:app: web-frontend spec:selector:app: web-frontendports:- port: 80name: httptargetPort: 8080 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:name: web-frontend spec:hosts:- *gateways:- ingressgateway80http:- route:- destination:host: web-frontend.default.svc.cluster.localport:number: 80kubectl apply -f web-frontend.yaml部署 Customers v1 和相应的资源 apiVersion: apps/v1 kind: Deployment metadata:name: customers-v1labels:app: customersversion: v1 spec:replicas: 1selector:matchLabels:app: customersversion: v1template:metadata:labels:app: customersversion: v1spec:containers:- image: customers:1.0.0imagePullPolicy: Alwaysname: svcports:- containerPort: 3000 --- kind: Service apiVersion: v1 metadata:name: customerslabels:app: customers spec:selector:app: customersports:- port: 80name: httptargetPort: 3000 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata:name: customers spec:host: customers.default.svc.cluster.localsubsets:- name: v1labels:version: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:name: customers spec:hosts:- customers.default.svc.cluster.localhttp:- route:- destination:host: customers.default.svc.cluster.localport:number: 80subset: v1fault:delay:percent: 50fixedDelay: 5skubectl apply -f customers-delay.yaml测试另开一个窗口循环请求 while true; do curl http://$GATEWAY_URL/; done 打开Grafana 进入Istio Service Dashboard你会发现客户端请求持续时间图上的持续时间增加了 打开zipkin选择serviceName和web-frontend.default然后添加minDuration条件输入 5s点击搜索按钮找到 trace。 点击其中一个 trace打开详细信息页面。在详情页上我们会发现持续时间是 5 秒。 单个 trace 有 4 个 span——点击 第3 个span代表从web-frontend到客户服务的请求。你会注意到在细节中response_flags标签设置为DI。“DI” 代表 “延迟注入”表示该请求被延迟了。 再次更新 VirtualService这一次我们将注入一个故障对 50% 的请求返回 HTTP 500 apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:name: customers spec:hosts:- customers.default.svc.cluster.localhttp:- route:- destination:host: customers.default.svc.cluster.localport:number: 80subset: v1fault:abort:httpStatus: 500percentage: value: 50kubectl apply -f customers-fault.yaml回到 Grafana 并打开 Istio Service Dashboard我们会注意到客户端的成功率在下降。 在 Zipkin 中也有类似的情况。如果我们再次搜索 trace我们可以删除最小持续时间我们会发现有错误的 trace 会以红色显示打开 Kiali通过点击 Graph 项查看服务图。 你会注意到web-frontend服务有一个红色的边框 点击web-frontend服务看看右边的侧边栏你会发现 HTTP 请求的细节。图中显示了成功和失败的百分比这两个数字都在 50% 左右这与我们在 VirtualService 中设置的百分比值相一致。
http://www.hkea.cn/news/14367683/

相关文章:

  • 网站怎么做备份温州专业做网站
  • 餐饮类网站建设达到的作用做电影网站的流程
  • 青岛做网站建网站网站通栏图片代码
  • 推广自身网站现在企业做网站用什么软件
  • 求职简历在哪个网站做网站建设合同规定
  • 淮安企业网站wordpress首页文章
  • 模块化局域网网站建设软件线上阿类电商平台
  • 连锁品牌网站建设广西建设教育网官网
  • 做网站用的系统东莞市智通人才招聘网
  • 部门网站建设怎么做学php搞网站开发
  • 做ppt素材的网站电脑做h5比较好的网站
  • 高端网站开发价格凯里网站设计公司哪家好
  • 域名注销期间网站还能打开吗企业网站特点和优势
  • 一台云服务器可以做多个网站优化网站排名技巧
  • 金华建设学校继续教育网站网页设计与制作实验报告总结
  • 爱用建站官网安徽网站建设开发电话
  • 网站制作完成后应进入什么阶段网站ui设计学的是什么
  • 大连做网站哪家便宜苏州wordpress
  • 网站logo位置哪个网站能接施工图来做
  • 领优惠券的网站怎么建设的wap网站制作模板
  • 网站建设自建的优点企业建筑网站有哪些类型有哪些
  • 国外用tornado做的网站wordpress 主题 不兼容
  • 服装网站建设优点有哪些电商网站多少钱
  • 移动卡套餐seo关键词排名优化费用
  • 杰商网站建设做外卖那些网站好
  • 做网站旅游销售网站建设收费标准资讯
  • 辽阳专业网站建设品牌wordpress去视频广告
  • 注册网站有什么风险吗找人做网站需要什么条件
  • 怀化网站优化免费查企业信息查询
  • 免费做明信片的网站素材羊设计师服务平台