Service的工作方式有三种:
第一种: 是Userspace方式
如下图描述, Client Pod要访问Server Pod时,它先将请求发给本机内核空间中的service规则,由它再将请求,
转给监听在指定套接字上的kube-proxy,kube-proxy处理完请求,并分发请求到指定Server Pod后,再将请求
递交给内核空间中的service,由service将请求转给指定的Server Pod。
由于其需要来回在用户空间和内核空间交互通信,因此效率很差,接着就有了第二种方式.
第二种: iptables模型
此工作方式是直接由内核中的iptables规则,接受Client Pod的请求,并处理完成后,直接转发给指定ServerPod.
第三种: ipvs模型
它是直接有内核中的ipvs规则来接受Client Pod请求,并处理该请求,再有内核封包后,直接发给指定的Server Pod。
注:
以上不论哪种,kube-proxy都通过watch的方式监控着kube-APIServer写入etcd中关于Pod的最新状态信息,
它一旦检查到一个Pod资源被删除了 或 新建,它将立即将这些变化,反应再iptables 或 ipvs规则中,以便
iptables和ipvs在调度Clinet Pod请求到Server Pod时,不会出现Server Pod不存在的情况。
自k8s1.1以后,service默认使用ipvs规则,若ipvs没有被激活,则降级使用iptables规则. 但在1.1以前,service
使用的模式默认为userspace.
查看k8s集群中API Server面向集群内部的service地址:
#其中第一个kubernets,类型为ClusterIP,暴露端口为443/tcp的即为APIServer的向集群内部提供服务的Service.
kubectl get svc
创建Service的清单文件:
kubectl explain svc
kubectl explain svc.spec
type:
service的类型有四种:
1. ExternalName: 用于将集群外部的服务引入到集群内部,在集群内部可直接访问来获取服务。
它的值必须是 FQDN, 此FQDN为集群内部的FQDN, 即: ServiceName.Namespace.Domain.LTD.
然后CoreDNS接受到该FQDN后,能解析出一个CNAME记录, 该别名记录为真正互联网上的域名.
如: www.test.com, 接着CoreDNS在向互联网上的根域DNS解析该域名,获得其真实互联网IP.
2. ClusterIP: 用于为集群内Pod访问时,提供的固定访问地址,默认是自动分配地址,可使用ClusterIP关键字指定固定IP.
3. NodePort: 用于为集群外部访问Service后面Pod提供访问接入端口.
这种类型的service工作流程为:
Client----->NodeIP:NodePort----->ClusterIP:ServicePort----->PodIP:ContainerPort
4. LoadBalancer: 用于当K8s运行在一个云环境内时,若该云环境支持LBaaS,则此类型可自动触发创建
一个软件负载均衡器用于对Service做负载均衡调度.
因为外部所有Client都访问一个NodeIP,该节点的压力将会很大, 而LoadBalancer则可解决这个问题。
而且它还直接动态监测后端Node是否被移除或新增了,然后动态更新调度的节点数。
#Service清单文件创建示例:
vim redis-svc.yaml #定义一个redis的服务.
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: default
spec:
selector: #指定标签选择器选择的标签范围.
app: redis
role: logstor
clusterIP: 10.97.97.97
type: ClusterIP
ports:
- name: redis
port: #设定Serivce对外提供服务的端口.
targetPort: #设定容器(Pod)的端口,即Pod网络的端口。
nodePort: #它仅在type为NodePort时才需要指定.
接着创建服务:
kubectl apply -f redis-svc.yaml
kubectl get svc
kubectl describe svc redis #可看到service redis它的详细配置信息.
Endpoints: 10.224.1.3x:6379 #这个就是Pod的地址,Serice和Pod实际上并非直接联系,中间
#还有一个Endpoint作为转发。所以这里显示的是Endpoint而非Pod.
K8s中资源的全局FQDN格式:
Service_NAME.NameSpace_NAME.Domain.LTD.
Domain.LTD.=svc.cluster.local. #这是默认k8s集群的域名。
创建一个nodePort类型的service,让节点外主机可以访问到服务.
vim myapp-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
selector:
app: myapp
release: canary
clusterIP: 10.99.99.99 #此地址设定为固定很容易冲突, 建议最好不写,让其自动分配.
type: NodePort
ports:
- port: #设置Service对外提供服务的端口
targetPort: # 设置Pod对外提供服务的端口.
nodePort: #此宿主机端口也可不指定,系统将自动从3万~65535分配,若必须设为80,也可以,
#但必须保证所以宿主机上的80端口没有被占用,若有被占用,则该节点上的服务将无法被访问.
Service的externalName类型原理介绍:
Pod---->SVC[externalName]------[SNAT]----->宿主机的物理网卡------>物理网关----->Internat上提供服务的服务器.
注意: Service是externelName类型时, externalName必须是域名,而且此域名必须能被CoreDNS或CoreDNS能通过
互联网上的根DNS解析出A记录.
Service在对外提供服务时,还支持会话粘性:
sessionAffinity : 它支持ClientIP 和 None两种方式.
None: 即不做会话粘性,进行随机调度.
ClientIP: 根据客户端IP来调度,同一个客户端IP都调度到同一个后端主机。
通过打补丁的方式来测试会话粘性:
#对上面创建的myapp service打补丁,让其支持基于ClientIP的会话粘性.
kubectl patch svc myapp -p ‘{"spec":{"sessionAffinity":"ClientIP"}}’
kubectl describe svc myapp #可以查看到多了一个Session Affinity的字段.
headless service(无头service):
所谓headless service指: 没有ClusterIP的service, 它仅有一个service name.这个服务名解析得到的不是
service的集群IP,而是Pod的IP,当其它人访问该service时,将直接获得Pod的IP,进行直接访问。
示例:
vim myapp-svc-headless.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-headless
namespace: default
spec:
selector:
app: myapp
release: canary
clusterIP: None
ports:
- port:
targetPort:
#创建headless service:
kubectl apply -f myapp-svc-headless.yaml
kubectl get svc #将可以看到ClusterIP项为None.
#这里将显示service name解析为Pod的IP了.
dig -t A myapp-headless.default.svc.cluster.local. @CoreDNS_IP
#CoreDNS_IP的查看方式:
kubectl get svc -n kube-system
#查看Pod的IP:
kubectl get pods -o wide -l app=myapp
Ingress Controller
下图即为Ingress Controller这种独特的控制器资源的工作流程图.
需要注意: Ingress Controller 和 Ingress是两个不同的资源。
Ingress它是通过headless service的集群内FQDN获取到它后端所有的Pod资源的IP,因为headless Service没有
ClusterIP,它的域名对应的IP为PodIP。Ingress获取PodIP后,在立刻将其写入到ingress-nginx的配置文件中,
并触发nginx重读配置文件。实现动态更新upstream。
另外,外部LB可以直接跳过Service,直接访问到nginx,这需要将nginx这个Pod作为共享宿主机的网络名称空间
才能实现,这时就需要借助于daemonSet控制器来控制着nginx这种七层反代Pod仅允许在指定节点上,并且
每个节点上仅运行一个nginx Pod。
#注:
DaemonSet,RepliceSet,Deployment,StatuefulSet 等它们都是Master上的ControllerManager
的子组件,而Ingress Controller则是独立运行的一个或一组Pod资源,它通常就是一个拥有七层
调度能力的应用程序,在K8s上这种应用程序有四种:
Nginx:一般默认使用Nginx作为这种应用程序。
Traefik: 它原先设计也是为微服务而生的,就是为了能实现动态生成配置文件。
Envoy: 在服务网格 或 微服务 中通常会比较喜欢用它.
Traefik和Envoy: 它们都可以实现动态监控配置文件发生变化,若发生变化,
则会即时自动重载配置,而无需手动参与。
HAProxy: 它是最不受欢迎的一种解决方案。
查看ingress controller的定义:
kubectl explain ingress
kubectl explain ingress.spec
创建名称空间的方式:
1. 使用命令:
kubectl create namespace test
kubectl get ns
kubectl delete ns/test #删除一个test名称空间, 需要注意: 删除一个名称空间,则会删除其内所有的资源.
2. 使用清单创建名称空间:
apiVersion: v1
kind: Namespace
metadata:
name: test
实现Ingress-ngnix的示例:
下面这个项目是kubernetes中ingress-nginx项目安装说明
https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md
#由于我是直接用VMware上的VM安装的K8s,因此使用裸机(Bare-metal)的方式来安装.
#首先,下载这个主配置文件,它里面帮我们写好了创建,Ingress-nginx所必须namespace,configMap,ServiceAccount,RBAC,Role,和ingress-nginx等.
# 在使用下面这清单文件时,建议先把ingress-nginx的镜像先下载下来,避免下载镜像失败导致创建ingress-nginx失败.
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
#接着, 下载裸机所对应的创建Ingress-nginx的Service配置清单.
https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml
#在继续之前先看下,当前的拓扑图
上面mandatory.yaml 帮我们创建了Nginx-Ingres-Controller,另外还有一些资源没有画出来.
service-nodeport.yaml 帮我们创建了Service/Ingress-nginx
#接着我们需要自己创建Ingress 和 Service/myapp 以及三个myapp Pod
vim deploy-demo.yaml
apiVersion: v1
kind: Service #这部分创建service/myapp
metadata:
name: myapp
namespace: default
spec:
selector: #通过下面两个标签(label)来选择Pod
app: myapp
release: canary
ports:
- name: http
targetPort:
port: ---
apiVersion: apps/v1
kind: Deployment #这部分来创建Myapp Pod的deployment.apps控制器
metadata:
name: myapp-ingress
namespace: default
spec:
replicas: #设置其副本数量控制器ReplicaSet,监控Pod至少保证有3个
selector:
matchLabels: #它筛选自己管理的Pod时,使用的label是下面两个.
app: myapp
release: canary
template: #replicaSet发现Pod不足时,使用此模板定义的规则,创建Pod.
metadata:
labels: #每次创建的Pod都打上下面两个label
app: myapp
release: canary
spec:
containers:
- name: myapp
image: harbor.zcf.com/k8s/myapp:v1
ports:
- name: http
containerPort:
#接着创建ingress
vim ingress-myapp.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-myapp
namespace: default #注意ingress要和后端提供Web服务的Pod处于同一名称空间中.
annotations:
#kubernetes.io为前缀,ingress.class:为键名,通过这种定义来告诉ingress,
#这里使用的ingress-controller为nginx,你在生成配置时,生成nginx相关的配置。
kubernetes.io/ingress.class: "nginx"
spec:
rules:
##定义使用虚拟主机来代理后端Web应用.而识别该虚拟主机的域名定义为myapp.test.com
- host: myapp.test.com
http:
paths:
- path:
backend:
#这里要指明后端提供Web服务的前端Service的名称,该Service负责筛选出提供Web服务的Pod.
serviceName: myapp
servicePort:
#以上四步,都完成后,我们就有了下面这些文件:
deploy-demo.yaml
ingress-myapp.yaml
mandatory.yaml
service-nodeport.yaml
. kubectl apply -f mandatory.yaml
#可验证以下信息: 其它信息的验证可参考扩展验证.
# kubectl get ns
NAME STATUS AGE
default Active 3d14h
ingress-nginx Active 6h12m
.....
# kubectl get deployments
# kubectl describe deployments myapp-ingress
# kubectl get replicaset
# kubectl describe replicaset myapp-ingress-5b8676cff7 . kubectl apply -f service-nodeport.yaml
#验证:
# kubectl get service -n ingress-nginx ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 172.30.245.115 <none> :/TCP,:/TCP 6h36m
. kubectl apply -f deploy-demo.yaml
. kubectl apply -f ingress-myapp.yaml
#验证:
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
client-f5cdb799f-2wsmr / Running 2d18h 10.10.97.37 192.168.111.80 <none> <none>
myapp-ingress-5b8676cff7-jxmg8 / Running 3h51m 10.10.97.60 192.168.111.80 <none> <none>
myapp-ingress-5b8676cff7-s2nsf / Running 3h51m 10.10.171.5 192.168.111.81 <none> <none>
myapp-ingress-5b8676cff7-wx5q7 / Running 3h51m 10.10.171.4 192.168.111.81 <none> <none> # kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
client / 2d18h
myapp-ingress / 3h52m # kubectl describe deployment myapp-ingress
Name: myapp-ingress
.......
Replicas: desired | updated | total | available | unavailable
StrategyType: RollingUpdate #deployment控制器默认的为滚动更新
MinReadySeconds:
RollingUpdateStrategy: % max unavailable, % max surge
......
NewReplicaSet: myapp-ingress-5b8676cff7 (/ replicas created)
...... # kubectl get replicaset
NAME DESIRED CURRENT READY AGE
client-f5cdb799f 2d18h
myapp-ingress-5b8676cff7 3h52m # kubectl describe replicasets.apps myapp-ingress-5b8676cff7
Name: myapp-ingress-5b8676cff7
Namespace: default
Selector: app=myapp,pod-template-hash=5b8676cff7,release=canary
..............
Annotations: deployment.kubernetes.io/desired-replicas:
deployment.kubernetes.io/max-replicas: #最多只允许多出一个副本,这说明,此ReplicaSet更新策略为:滚动更新,即先创建一个,然后在删除一个。
deployment.kubernetes.io/revision:
Controlled By: Deployment/myapp-ingress #上游控制器是myapp-ingress,控制器类型: deployment
Replicas: current / desired #副本数量, 当前3个,期望3个
Pods Status: Running / Waiting / Succeeded / Failed
5. 进入nginx-ingress-controller中,查看OpenResty的配置文件:
kubectl exec -n ingress-nginx -it nginx-ingress-controller-.... -- /bin/sh
$ cat nginx.conf
#这里面,内容很多,可只看重点部分
# 1. server_name myapp.test.com #这个server段,可重点看。
# 2. upstream upstream_balancer {} #这段可参考,因为它可能是通过balancer_by_lua_block {} 实现获取Pod列表的.而该段调用的是ruby脚本,我暂时没看懂。
6. 测试访问:
再集群外部主机*问: 必须能解析 myapp.test.com 这个域名.
http://myapp.test.com:53712/
<h1>WERCOME TO www.zcf.com WEB SITE | Sun Jul 21 02:13:51 UTC 2019 | myapp-ingress-5b8676cff7-s2nsf | 10.10.171.5 | -v1- | </h1>
实验总结:
当ingress创建完成后,就相当于它将ingress-controller 和 后端提供Web服务的Pod关联起来了。
Pod的前端Service负责实时监控Pod的变化,并反应在自己的Endpoints中,而ingress通过定义backend为后端Service,从而与后端的Service取得联系,并获取Service的Endpoints列表,从而得到它所监控的Pod列表,这些Pod就是实际提供Web服务的后端容器。
当Ingress获取到后端Pod列表后,它就可以联系前端的ingress-controller,并根据自己annotations中的定义知道前端ingress-controller所使用的反向代理为nginx,然后ingress就会生成nginx的配置信息,并自定写入ingress-controller-nginx中。当ingress-controller-nginx获得配置信息后,它就可以对外提供反向代理服务了。
另外:
ingress中定义rules,指明使用虚拟主机,虚拟主机的域名为myapp.test.com,若有多个虚拟主机,则可定义多个。那么它生成的nginx配置就是定义一个server,并指明其servername为myapp.test.com ,该虚拟主机的location / { proxy_pass http://upstream }可以简单这么理解,若有多个虚拟主机,就是定义多个server,每个server都要有独立的域名,比如论坛,商城,博客等。
location中定义的proxy_pass 的upstream的后端服务器地址列表,则是由ingress中backend定义的serviceName所指定的myapp这个service所监控的后端Pod。
这样以来整个访问链条就构建完成了。
以上四步创建的结构如下图 【注: nginx-ingress-controller 就是我要说明的 ingress-controller-nginx,再书写时写错了】
但需要注意,ingress仅是动态监控service所监控的后端Pod是否发生变化了,若发生变化,它会立即生成nginx的最新upstream配置,然后再次注入配置到ingress-controller-nginx中,这样ingress-controller-nginx就可以实时知道后端Pod的变化,并直接将前端Client的访问流量代理给后端Pod,图中看上去要先经过ingress,再转发给Pod,实际上是ingress-controller-nginx直接将请求转发给Pod,因为ingress已经将Pod的地址写入到nginx的upstream中了。
下面示例演示配置一个tomcat的七层代理应用:
vim tomcat-deploy.yaml
apiVersion: v1
kind: Service
metadata:
#这个名字可根据需要定义, 如: 是一个电商站点,则可取名为 eshop 等名字.
name: tomcat
namespace: default
spec:
selector:
app: tomcat
release: canary
ports:
- name: http
targetPort:
port:
- name: ajp
targetPort:
port:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-deploy
namespace: default
spec:
replicas:
selector:
matchLabels:
app: tomcat
release: canary
template:
metadata:
labels:
app: tomcat
release: canary
spec:
containers:
- name: tomcat
image: tomcat:8.5.-jre8-alpine
ports:
- name: http
containerPort:
ports:
- name: ajp
containerPort:
以上配置说明:
它定义了一个Deployment的控制器,它下面有3个tomcat Pod,并且都暴露了8080和8009端口,然后还定义了一个service,此service将自己的8080端口映射到Pod的8080端口上,8009也一样。这个service并不作为访问这些tomcat Pod的统一入口,而是作为ingress获取这些tomcat Pod的IP而存在的。
下面测试创建一个TLS类型的secret,然后实现使用同一套证书为两个网站提供HTTPS
1. 使用Kubeasz部署的集群在制作证书时,必须使用cfssl工具来做,因为kubeasz是使用此工具来做证书的,它制作证书的字符编码与OpenSSL的字符编码不同,因此你若使用cfssl制作的ca证书给Openssl制作的证书签证,是不可以的,但若能修改Openssl默认证书中的字符编码,应该是可以的,但我没有研究过如何修改。
cd /etc/kubernetes/ssl #这是kubeasz部署后,CA证书默认存放位置。
cp admin-csr.json test.com-csr.json
vim test.com-csr.json
{
"CN": "test.com",
"key": {
"algo": "rsa",
"size":
},
"names": [
{
"C": "CN",
"ST": "HangZhou",
"L": "XS"
}
]
} # grep -C1 'profile' ca-config.json
},
"profiles": {
"kubernetes": { # cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes test.com-csr.json | cfssljson -bare test.com
#创建好的证书,不能直接放到nginx中使用,这个证书必须做出k8s中的资源对象,然后,让nginx来引用这个对象才行.
kubectl create secret tls website-ingress-secret --cert=website.crt --key=website.key
注:
tls: 是要创建secret的类型。
tomcat-ingress-secret:是这个secret的名字.
--cert: 指明TLS类型的secret所使用的证书在哪里。
--key: 指明证书的私钥的位置
kubectl get secret #查看创建的secret对象
kubectl describe secret website-ingress-secret #查看tomcat-ingress-secret对象的详细信息。
有了secret对象后,就可以创建基于HTTPS的tomcat访问了.
vim ingress-tomcat-tls.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-website-tls
namespace: default
annotations:
kubernetes.io/ingress.class: “nginx”
spec:
tls:
- hosts:
#这里的列表可定义多个主机, 意思是这个多个主机都将使用相同的证书来加密响应数据.这就是所谓的SNI
- tomcat.test.com
- myapp.test.com
secretName: website-ingress-secret
rules: #rules可定义多个, 每一个就是一个虚拟主机 或 URL映射.
- host: tomcat.test.com
http:
paths:
- path:
backend:
serviceName: tomcat
servicePort:
- host: myapp.test.com
http:
paths:
- path:
backend:
serviceName: myapp
servicePort:
以上做好以后,就可以创建支持TLS的ingress了.
kubectl apply -f ingress-tomcat-tls.yaml
kubectl get ingress
kubectl describe ingress ingress-tomcat-tls
# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 172.30.245.115 <none> 80:53712/TCP,443:46652/TCP 9h
kubectl exec -n ingress-nginx -it nginx-ingress-controller-x... -- /bin/sh
#登陆后可查看nginx的配置文件,确认一下tomcat是否支持HTTPS.
最后,测试访问:
https://tomcat.test.com:46652/
#测试发现,Client打开网页后,查看证书,竟然是Kubernetes Ingress Controller颁发的证书,这是怎么回事?
#目前我还没有找到答案,希望路过的大牛们,多多指点,万分感谢....
K8s Service原理介绍的更多相关文章
-
K8s configMap原理介绍
给容器内应用程序传递参数的实现方式: 1. 将配置文件直接打包到镜像中,但这种方式不推荐使用,因为修改配置不够灵活. 2. 通过定义Pod清单时,指定自定义命令行参数,即设定 args:[" ...
-
03 Yarn 原理介绍
Yarn 原理介绍 大纲: Hadoop 架构介绍 YARN 产生的背景 YARN 基础架构及原理 Hadoop的1.X架构的介绍 在1.x中的NameNodes只可能有一个,虽然可以通过Se ...
-
kafka集群原理介绍
目录 kafka集群原理介绍 (一)基础理论 二.配置文件 三.错误处理 kafka集群原理介绍 @(博客文章)[kafka|大数据] 本系统文章共三篇,分别为 1.kafka集群原理介绍了以下几个方 ...
-
1.1_springboot2.x与缓存原理介绍&使用缓存
一.springboot与缓存介绍&使用缓存 1.JSR107 JAVA Cahing定义了5个核心接口,分别是CachingProvider.CacheManager.Cache.Entry ...
-
Spring MVC工作原理及源码解析(一) MVC原理介绍、与IOC容器整合原理
MVC原理介绍 Spring MVC原理图 上图是Spring MVC工作原理图(图片来自网上搜索),根据上图,我们可以得知Spring MVC的工作流程如下: 1.用户(客户端,即浏览器)发送请求至 ...
-
04 MapReduce原理介绍
大数据实战(上) # MapReduce原理介绍 大纲: * Mapreduce介绍 * MapReduce2运行原理 * shuffle及排序 定义 * Mapreduce 最早是由googl ...
-
Android Animation学习(一) Property Animation原理介绍和API简介
Android Animation学习(一) Property Animation介绍 Android Animation Android framework提供了两种动画系统: property a ...
-
[转]MySQL主从复制原理介绍
MySQL主从复制原理介绍 一.复制的原理 MySQL 复制基于主服务器在二进制日志中跟踪所有对数据库的更改(更新.删除等等).每个从服务器从主服务器接收主服务器已经记录到其二进制日志的保存的更新,以 ...
-
分布式文件系统FastDFS原理介绍
在生产中我们一般希望文件系统能帮我们解决以下问题,如:1.超大数据存储:2.数据高可用(冗余备份):3.读/写高性能:4.海量数据计算.最好还得支持多平台多语言,支持高并发. 由于单台服务器无法满足以 ...
随机推荐
-
Big Event in HDU[HDU1171]
Big Event in HDU Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
-
android 64 sd卡读写的操作
package com.itheima.writesd; import java.io.File; import java.io.FileNotFoundException; import java. ...
-
BZOJ1941:[SDOI2010]Hide and Seek(K-D Tree)
Description 小猪iPig在PKU刚上完了无聊的猪性代数课,天资聪慧的iPig被这门对他来说无比简单的课弄得非常寂寞,为了消除寂寞感,他决定和他的好朋友giPi(鸡皮)玩一个更加寂寞的游戏- ...
-
JSON—序列化
表单数据的序列化 用SerializeArray()将有效控件序列化为JSON对象数组? 包含name和value两个属性 SerializeArray()检测一组表单元素中的有效控件? 1.没有 ...
-
convertTo函数
前言 使用opencv常常会需要用到数据类型之间的转换,此时需要使用convertTo函数. 代码: cv::Mat samples; cv::Mat tdata; samples.convertTo ...
-
【BZOJ】【1089】【SCOI2003】严格n元树
高精度/递推 Orz Hzwer…… 然而我想多了…… 理解以后感觉黄学长的递推好精妙啊 顺便学到了一份高精度的板子= =233 引用下题解: f[i]=f[i-1]^n+1 ans=f[d]-f[d ...
-
jdbc连接sql server2017进行简单的增、删、改、查操作
这几天刚做完数据库的课程设计,来稍微总结一下如何通过jdbc访问sql server数据库进行简单的增删改查操作.在连接之前,需要简单地配置一下,包括下载对应jdk版本的驱动,设置环境变量等等.相关配 ...
-
00106_UDP通信
1.DatagramPacket (1)JDK中提供了一个DatagramPacket类,该类的实例对象就相当于一个集装箱,用于封装UDP通信中发送或者接收的数据: (2)在创建发送端和接收端的Dat ...
-
12.boost有向图无向图(矩阵法)
#include <iostream> #include <boost/config.hpp> //图 #include <boost/graph/adjacency_m ...
-
51nod 最大子矩阵和
一个M*N的矩阵,找到此矩阵的一个子矩阵,并且这个子矩阵的元素的和是最大的,输出这个最大的值. 我们可以降维,枚举矩形的长,然后算出一个一维数组,然后就转化成了最大字段和问题 #include< ...