首页 文章 精选 留言 我的

精选列表

搜索[解决方案],共10002篇文章
优秀的个人博客,低调大师

阿里云深度学习存储解决方案

介绍 现如今在谈论数据的价值的时候,经常提到的概念之一就是深度学习,或者更广泛的说是人工智能。深度学习系统通常通过大规模的数据集和神经网络算法来训练和完善应用模型,这就需要强大的计算集群,高性能可扩展的存储系统来实现。 深度学习的基本概念 人工智能(AI,Artificial Intelligence)指由人制造出来的机器所表现出来的智能,通常AI尝试创造类人的用于通用目的的智能设备。 机器学习(ML,Machine Learning)是AI的一个分支,通常通过训练的方式来解决特定的问题,例如图片识别,语音识别等。 深度学习(DL,Deep Learning)是机器学习的一个分支,通常指机器学习中使用的神经网络算法超过一层,就称为深度学习。其中最经常使用的是卷积神经网络(CNN,Convolutional Neural Networks),

优秀的个人博客,低调大师

J2EE--SSO解决方案

提醒:文档只是作为一个基础的参考,愿意了解的朋友可以随时咨询。 第一节:单点登录简介 第一步:了解单点登录 SSO主要特点是: SSO应用之间使用Web协议(如HTTPS),并且只有一个登录入口. SSO的体系中有下面三种角色: 1) User(多个) 2) Web应用(多个) 3) SSO认证中心(一个) SSO实现包含以下三个原则: 1)所有的登录都在SSO认证中心进行。 2) SSO认证中心通过一些方法来告诉Web应用当前访问用户究竟是不是通过认证的用户. 3) SSO认证中心和所有的Web应用建立一种信任关系. CAS的基本原理CAS(Central Authentication Service)是Yale耶鲁大学发起的构建Web SSO的Java开源项目。 1.CAS术语解释: SSO-Single Sign On单点登录 TGT-Ticket Granting Ticket用户身份认证凭证票据 ST-Service Ticket服务许可凭证票据 TGC-Ticket Granting Cookie存放用户身份认证凭证票据的cookie. 第二步:了解单点登录体系结构 1)CAS Server负责完成对用户信息的认证,需要单独部署,CAS Server会处理用户名/密码等凭证(Credentials). 2)CAS Client部署在客户端,当有对本地Web应用受保护资源的访问请求,并且需要对请求方进行身份认证,重定向到CAS Server进行认证. 第三步:单点登录环境准备工作 1)cas-server-3.5.0-release.zip(CAS服务端) 2)cas-client-3.3.3-release.zip(CAS客户端) 3)apache-tomcat-7.0.40 4)cas-client-core-3.2.1.jar 5)cas-server-core-3.5.0.jar 6)cas-server-support-jdbc-3.5.0.jar 第二节:单点登录环境搭建与部署 第一步:环境部署 1.通过Java JDK生成证书三部曲 证书对于实现此单点登录非常之重要,证书是服务器端和客户端安全通信的凭证,本教程只是演示,所有用了JDK自带的证书生成工具keytool。 当然在实际项目中你可以到专门的证书认证中心购买证书。 使用JDK自带的keytool生成证书 第一步生成证书: keytool -genkey -alias mycacerts -keyalg RSA -keystore C:/common/keys/keycard 注意:输入相关信息用于生成证书.其中名字与姓氏这一最好写你的域名,如果在单击测试你可以在C:WindowsSystem32driversetchosts文件中映射一个虚拟域名, 注意不要写IP。 第二步导出证书: keytool -export -file C:/common/keys/keycard.crt -alias mycacerts -keystoreC:/common/keys/keycard 第三步导入到JDK安装目录证书: keytool -import -keystore C:/"ProgramFiles"/Java/jdk1.6.0_32/jre/lib/security/cacerts -fileC:/common/keys/keycard.crt -alias mycacerts 2.解压cas-server-3.5.0-release.zip文件, 在cas-server-3.5.0-releasecas-server-3.5.0modules目录下找到cas-server-webapp-3.5.0.war文件并命名为cas.war,并复制到在Tomcat根目录的webapps目录下, 如下图: 3.修改host文件(C:WindowsSystem32driversetc)hosts文件中添加添加以下配置 127.0.0.1 jeesz.cn (配置自己的域名.) 注意:如果想在一台PC机上模拟这个单点登录,就必须域名重定向,如果是多台PC机,可以不配置此项,下文有用到fast-web.cn,可以用相应PC机的IP代替 4.修改Tomcat文件下的server.xml(apache-tomcat-7.0.40confserver.xml)添加以下内容: 在server.xml文件中把 maxThreads="150" scheme="https"secure="true" clientAuth="false" sslProtocol="TLS" /> 修改成如下: port="8443" protocol="org.apache.coyote.http11.Http11Protocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystoreFile="C:/common/keys/keycard" keystorePass="xxxxxx " ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA" /> 5.启动Tomcat服务,查看信息,(如果有报错,可以根据信息查找错误),打开浏览器,输入http://jeesz.cn:8080/cas如果出现以下界面,则代表CAS服务端配置成功。 注:这个是最简单的CAS服务,只要输入的用户名跟密码一样,就可以正常登陆,在我们实际开发中,这个验证因为跟数据库作比较,接下来,我们就配置数据库校验。 第二步:配置数据库验证 1.在apache-tomcat-7.0.2webappscasWEB-INF目录下找到deployerConfigContext.xml文件,找到如下代码: 添加下面代码: 这里sql属性是从user表中根据cas登陆名查找密码--> 2.增加数据源dataSource, 在deployerConfigContext.xml,(跟上面同一个文件)找到 ,在下面添加如下代码: com.mysql.jdbc.Driver jdbc:mysql://127.0.0.1:3306/sso根据自己的数据库URL地址--> root根据自己的数据库用户名--> 根据自己的数据库密码--> 3.数据库添加用户表及数据(这里用的mysql),比如在mysql数据库中有t_user表 4.增加jar包,cas-client-core-3.2.1.jar、cas-server-core-3.5.0.jar、cas-server-support-jdbc-3.5.0.jar包拷贝到apache-tomcat-7.0.2webappscasWEB-INFlib目录下。 5.重启Tomcat,打开浏览器,输入http://jeesz.cn:8080/,输入数据库里的用户名和密码,如果出现如下界面,则配置成功。 现在我们的CAS服务端已经配置好了,接下来,我们配置客户端 第二节:配置自己的Web工程(客户端) 1.在host文件下,添加如下代码: 127.0.0.1 www.sso1.com 127.0.0.1www.sso2.com 注意:这个网址最好不要用互联网已经存在的域名,否则你将无法访问该地址。 如果想在一台PC机上模拟这个单点登录,就必须域名重定向,如果是多台PC机,可以不配置此项,下文有用到www.sso1.com,www.sso2.com,可以用相应PC机的IP代替 1.在Tomcat根目录下创建一个sso1,sso2目录。如下如: 2在eclipse新建两个web工程,分别为sso1,sso2。 3在自己的Web工程里加入cas-client-core.jar,commons-logging-1.1.jar,(解压cas-client-3.2.0-release.zip,在cas-client-3.2.0-release.zipcas-client-3.2.0modules,找到该JAR包) 分别加入到sso1,sso2工程的lib里。

优秀的个人博客,低调大师

《MMO类游戏解决方案》重磅发布

随着游戏行业的发展,休闲类、卡牌类游戏已经无法满足玩家对高品质游戏的追求,同时移动终端硬件配置也在飞速提升,满足了MMO RPG、MOBA等中重度游戏运行对硬件的要求,越来越多的MMO类产品随之诞生。 目前,游戏产品同质化现象严重,游戏厂商已经从爆发式增长时代逐步回归理性,未来将走精品化路线和全球化路线。未来MMO类游戏在精品化游戏中将持续扮演非常重要的角色,但同时也面临着诸多技术挑战: • 大带宽高包量:接入层需要具备充足的网络带宽和较高的网络包吞吐能力。 • 资源弹性伸缩:短平快的行业特性,需要最大化地节约和利用游戏服务器资源。 • 高计算能力:MMO类型的网游属于强交互强校验类型,对游戏服务器的计算能力有比较高的要求。 • 就近接入:为保证游戏流畅性,提升游戏体验,游戏玩家需要就近接入方式连接游戏服务器。 因此,

优秀的个人博客,低调大师

Docker网络解决方案-Flannel部署记录

Docker跨主机容器间网络通信实现的工具有Pipework、Flannel、Weave、Open vSwitch(虚拟交换机)、Calico实现跨主机容器间的通信。其中Pipework、Weave、Flannel,三者的区别是: Weave的思路 1 2 在每个宿主机上布置一个特殊的route的容器,不同宿主机的route容器连接起来。route拦截所有普通容器的ip请求,并通过udp包发送到其他宿主机上的普通容器。 这样在跨机的多个容器端看到的就是同一个扁平网络。weave解决了网络问题,不过部署依然是单机的。 Flannel的思路 1 2 3 4 5 6 7 8 9 10 11 12 13 Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。但在默认的Docker配置中, 每个节点上的Docker服务会分别负责所在节点容器的IP分配。这样导致的一个问题是,不同节点上容器可能获得相同的内外IP地址。并使这些容器之间能够之间通过IP地址相互找到,也就是相 互 ping 通。 Flannel的设计目的就是为集群中的所有节点重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得 "同属一个内网" 且 "不重复的" IP地址,并让属于不同节点上的容器能够直接通过内网IP通信。 Flannel实质上是一种 "覆盖网络(overlaynetwork)" ,即表示运行在一个网上的网(应用层网络),并不依靠ip地址来传递消息,而是采用一种映射机制,把ip地址和identifiers做映射来资源定位。也就 是将TCP数据包装在另一种网络包里面进行路由转发和通信,目前已经支持UDP、VxLAN、AWSVPC和GCE路由等数据转发方式。 原理是每个主机配置一个ip段和子网个数。例如,可以配置一个覆盖网络使用10.100.0.0 /16 段,每个主机 /24 个子网。因此主机a可以接受10.100.5.0 /24 ,主机B可以接受10.100.18.0 /24 的包。flannel使用etcd来维护分配的子网到实际的ip地址之间的映射。对于数据路径,flannel使用udp来封装ip数据报,转发到远程主机。选择UDP作为转发协议是因为他能穿透防火墙。例如,AWSClassic无法转发IPoIPorGRE网络包,是因为它的安全组仅仅支持TCP /UDP/ICMP 。 flannel使用etcd存储配置数据和子网分配信息。flannel启动之后,后台进程首先检索配置和正在使用的子网列表,然后选择一个可用的子网,然后尝试去注册它。 etcd也存储这个每个主机对应的ip。flannel使用etcd的 watch 机制监视 /coreos .com /network/subnets 下面所有元素的变化信息,并且根据他来维护一个路由表。为了提高性能,flannel优化了UniversalTAP /TUN 设备,对TUN和UDP之间的ip分片做了代理。 默认的节点间数据通信方式是UDP转发.在Flannel的GitHub页面有如下的一张原理图: 对上图的简单解释: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1)数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,这是个P2P的虚拟网卡,flanneld服务监听在网卡的另外一端。 2)Flannel通过Etcd服务维护了一张节点间的路由表,在稍后的配置部分我们会介绍其中的内容。 3)源主机的flanneld服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flanneld服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡, 然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一下的有docker0路由到达目标容器。 这样整个数据包的传递就完成了,这里需要解释三个问题: 1)UDP封装是怎么回事? 在UDP的数据内容部分其实是另一个ICMP(也就是 ping 命令)的数据包。原始数据是在起始节点的Flannel服务上进行UDP封装的,投递到目的节点后就被另一端的Flannel服务 还原成了原始的数据包,两边的Docker服务都感觉不到这个过程的存在。 2)为什么每个节点上的Docker会使用不同的IP地址段? 这个事情看起来很诡异,但真相十分简单。其实只是单纯的因为Flannel通过Etcd分配了每个节点可用的IP地址段后,偷偷的修改了Docker的启动参数。 在运行了Flannel服务的节点上可以查看到Docker服务进程运行参数( ps aux| grep docker| grep "bip" ),例如“--bip=182.48.25.1 /24 ”这个参数,它限制了所在节 点容器获得的IP范围。这个IP范围是由Flannel自动分配的,由Flannel通过保存在Etcd服务中的记录确保它们不会重复。 3)为什么在发送节点上的数据会从docker0路由到flannel0虚拟网卡,在目的节点会从flannel0路由到docker0虚拟网卡? 例如现在有一个数据包要从IP为172.17.18.2的容器发到IP为172.17.46.2的容器。根据数据发送节点的路由表,它只与172.17.0.0 /16 匹配这条记录匹配,因此数据从docker0 出来以后就被投递到了flannel0。同理在目标节点,由于投递的地址是一个容器,因此目的地址一定会落在docker0对于的172.17.46.0 /24 这个记录上,自然的被投递到了docker0网卡。 Pipework的思路 1 2 3 4 5 pipework是一个单机的工具,组合了brctl等工具,可以认为pipework解决的是宿主机上的设置容器的虚拟网卡、网桥、ip等,可以配合其他网络使用。详情可参考:Docker网络详解及pipework源码解读与实践 如果容器数量不多,想简单的组一个大的3层网络,可以考虑weave 如果容器数量很多,而且你们的环境复杂,需要多个子网,可以考虑 open vswitch或者fannel weave的总体网络性能表现欠佳,flannelVXLAN能满足要求,一般推荐用flannel ------------------------------------------------------------------------------------------------------------------------ Flannel环境部署记录 1)机器环境(CentOS7系统) 1 2 10.10.172.201部署etcd,flannel,docker主机名:node1主控端(通过etcd) 10.10.172.202部署flannel,docker主机名:node2被控端 2)node1(10.10.172.201)机器操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 设置主机名及绑定hosts [root@node1~] #hostnamectl--staticset-hostnamenode1 [root@node1~] #vim/etc/hosts 10.10.172.201node1 10.10.172.201etcd 10.10.172.202node2 关闭防火墙,如果开启防火墙,则最好打开2379和4001端口 [root@node1~] #systemctldisablefirewalld.service [root@node1~] #systemctlstopfirewalld.service 先安装docker环境 [root@node1~] #yuminstalldocker-y 安装etcd k8s运行依赖etcd,需要先部署etcd,下面采用yum方式安装: [root@node1~] #yuminstalletcd-y yum安装的etcd默认配置文件在 /etc/etcd/etcd .conf,编辑配置文件: [root@node1~] #cp/etc/etcd/etcd.conf/etc/etcd/etcd.conf.bak [root@node1~] #cat/etc/etcd/etcd.conf #[member] ETCD_NAME=master #节点名称 ETCD_DATA_DIR= "/var/lib/etcd/default.etcd" #数据存放位置 #ETCD_WAL_DIR="" #ETCD_SNAPSHOT_COUNT="10000" #ETCD_HEARTBEAT_INTERVAL="100" #ETCD_ELECTION_TIMEOUT="1000" #ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380" ETCD_LISTEN_CLIENT_URLS= "http://0.0.0.0:2379,http://0.0.0.0:4001" #监听客户端地址 #ETCD_MAX_SNAPSHOTS="5" #ETCD_MAX_WALS="5" #ETCD_CORS="" # #[cluster] #ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380" #ifyouusedifferentETCD_NAME(e.g.test),setETCD_INITIAL_CLUSTERvalueforthisname,i.e."test=http://..." #ETCD_INITIAL_CLUSTER="default=http://localhost:2380" #ETCD_INITIAL_CLUSTER_STATE="new" #ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_ADVERTISE_CLIENT_URLS= "http://etcd:2379,http://etcd:4001" #通知客户端地址 #ETCD_DISCOVERY="" #ETCD_DISCOVERY_SRV="" #ETCD_DISCOVERY_FALLBACK="proxy" #ETCD_DISCOVERY_PROXY="" 启动etcd并验证状态 [root@node1~] #systemctlstartetcd [root@node1~] #systemctlenableetcd [root@node1~] #ps-ef|grepetcd etcd151481013:10?00:00:00 /usr/bin/etcd --name=master #节点名称--data-dir=/var/lib/etcd/default.etcd#数据存放位置--listen-client-urls=http://0.0.0.0:2379,http://0.0.0.0:4001#?听客户端地址 root1550615419013:11pts /0 00:00:00 grep --color=autoetcd [root@node1~] #lsof-i:2379 COMMANDPIDUSERFDTYPEDEVICESIZE /OFF NODENAME etcd15148etcd6uIPv6489110t0TCP*:2379(LISTEN) etcd15148etcd11uIPv4480550t0TCPlocalhost:44959->localhost:2379(ESTABLISHED) etcd15148etcd15uIPv6480610t0TCPlocalhost:2379->localhost:44959(ESTABLISHED) [root@node1~] #etcdctlsettestdir/testkey00 0 [root@node1~] #etcdctlgettestdir/testkey0 0 [root@node1~] #etcdctl-Chttp://etcd:4001cluster-health member8e9e05c52164694dishealthy:gothealthyresultfromhttp: //etcd :2379 clusterishealthy [root@node1~] #etcdctl-Chttp://etcd:2379cluster-health member8e9e05c52164694dishealthy:gothealthyresultfromhttp: //etcd :2379 clusterishealthy 安装覆盖网络Flannel [root@node1~] #yuminstallflannel-y 配置Flannel [root@node1~] #cp/etc/sysconfig/flanneld/etc/sysconfig/flanneld.bak [root@node1~] #vim/etc/sysconfig/flanneld #Flanneldconfigurationoptions #etcdurllocation.Pointthistotheserverwhereetcdruns FLANNEL_ETCD_ENDPOINTS= "http://etcd:2379" #etcdconfigkey.Thisistheconfigurationkeythatflannelqueries #Foraddressrangeassignment FLANNEL_ETCD_PREFIX= "/atomic.io/network" #Anyadditionaloptionsthatyouwanttopass #FLANNEL_OPTIONS="" 配置etcd中关于flannel的key(这个只在安装了etcd的机器上操作) Flannel使用Etcd进行配置,来保证多个Flannel实例之间的配置一致性,所以需要在etcd上进行如下配置( '/atomic.io/network/config' 这个key与上文 /etc/sysconfig/flannel 中的配置项FLANNEL_ETCD_PREFIX是相对应的,错误的话启动就会出错): [root@node1~] #etcdctlmk/atomic.io/network/config'{"Network":"10.10.0.0/16"}' { "Network" : "10.10.0.0/16" } 温馨提示:上面flannel设置的ip网段可以任意设定,随便设定一个网段都可以。容器的ip就是根据这个网段进行自动分配的,ip分配后,容器一般是可以对外联网的(网桥模式,只要宿主机能上网就可以) 启动Flannel [root@node1~] #systemctlenableflanneld.service [root@node1~] #systemctlstartflanneld.service [root@node1~] #ps-ef|grepflannel root157301013:16?00:00:00 /usr/bin/flanneld -etcd-endpoints=http: //etcd :2379-etcd-prefix= /atomic .io /network root1587315419013:16pts /0 00:00:00 grep --color=autoflannel 启动Flannel后,一定要记得重启docker,这样Flannel配置分配的ip才能生效,即docker0虚拟网卡的ip会变成上面flannel设定的ip段 [root@node1~] #systemctlrestartdocker [root@node1~] #systemctlenabledocker 3)node2(10.10.172.202)机器操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 设置主机名及绑定hosts [root@node2~] #hostnamectl--staticset-hostnamenode2 [root@node2~] #vim/etc/hosts 10.10.172.201node1 10.10.172.201etcd 10.10.172.202node2 关闭防火墙,如果开启防火墙,则最好打开2379和4001端口 [root@node2~] #systemctldisablefirewalld.service [root@node2~] #systemctlstopfirewalld.service 先安装docker环境 [root@node2~] #yuminstalldocker-y 安装覆盖网络Flannel [root@node2~] #yuminstallflannel-y 配置Flannel [root@node2~] #cp/etc/sysconfig/flanneld/etc/sysconfig/flanneld.bak [root@node2~] #vim/etc/sysconfig/flanneld #Flanneldconfigurationoptions #etcdurllocation.Pointthistotheserverwhereetcdruns FLANNEL_ETCD_ENDPOINTS= "http://etcd:2379" #etcdconfigkey.Thisistheconfigurationkeythatflannelqueries #Foraddressrangeassignment FLANNEL_ETCD_PREFIX= "/atomic.io/network" #Anyadditionaloptionsthatyouwanttopass #FLANNEL_OPTIONS="" 启动Flannel [root@node2~] #systemctlenableflanneld.service [root@node2~] #systemctlstartflanneld.service [root@node2~] #ps-ef|grepflannel root317651013:20?00:00:00 /usr/bin/flanneld -etcd-endpoints=http: //etcd :2379-etcd-prefix= /atomic .io /network root3181431576013:20pts /0 00:00:00 grep --color=autoflannel 启动Flannel后,一定要记得重启docker,这样Flannel配置分配的ip才能生效,即docker0虚拟网卡的ip会变成上面flannel设定的ip段 [root@node2~] #systemctlrestartdocker [root@node2~] #systemctlenabledocker 4)创建容器,验证跨主机容器之间的网络联通性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 首先在node1(10.10.172.201)上容器容器,如下,登陆容器发现已经按照上面flannel配置的分配了一个ip段(每个宿主机都会分配一个182.48.0.0 /16 的网段) [root@node1~] #dockerrun-ti-d--name=node1.testdocker.io/nginx/bin/bash 2dea24b1562f3d4dc89cde3fa00c707276edcfba1c8f3b0ab4c62e075e63de2f [root@node1~] #dockerexec-tinode1.test/bin/bash root@2dea24b1562f:/ #apt-getupdate&&apt-getinstalliprouteiputils-ping-y root@2dea24b1562f:/ #ipaddr 1:lo:<LOOPBACK,UP,LOWER_UP>mtu65536qdiscnoqueuestateUNKNOWNgroupdefault link /loopback 00:00:00:00:00:00brd00:00:00:00:00:00 inet127.0.0.1 /8 scopehostlo valid_lftforeverpreferred_lftforever inet6::1 /128 scopehost valid_lftforeverpreferred_lftforever 7:eth0@if8:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1472qdiscnoqueuestateUPgroupdefault link /ether 02:42:0a:0a:5c:02brdff:ff:ff:ff:ff:fflink-netnsid0 inet10.10.92.2 /24 scopeglobaleth0 valid_lftforeverpreferred_lftforever inet6fe80::42:aff:fe0a:5c02 /64 scopelink valid_lftforeverpreferred_lftforever 接着在node2(10.10.172.202)上容器容器 [root@node2~] #dockerrun-ti-d--name=node2.testdocker.io/nginx/bin/bash 374417e9ce5bcd11222d8138e684707c00ca8a4b7a16243ac5cfb1a8bd19ee6e [root@node2~] #dockerexec-tinode2.test/bin/bash root@374417e9ce5b:/ #cat/etc/debian_version 9.3 root@374417e9ce5b:/ #apt-getupdate&&apt-getinstalliprouteiputils-ping-y root@374417e9ce5b:/ #ipaddr 1:lo:<LOOPBACK,UP,LOWER_UP>mtu65536qdiscnoqueuestateUNKNOWNgroupdefault link /loopback 00:00:00:00:00:00brd00:00:00:00:00:00 inet127.0.0.1 /8 scopehostlo valid_lftforeverpreferred_lftforever inet6::1 /128 scopehost valid_lftforeverpreferred_lftforever 469:eth0@if470:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1472qdiscnoqueuestateUPgroupdefault link /ether 02:42:0a:0a:1d:02brdff:ff:ff:ff:ff:fflink-netnsid0 inet10.10.29.2 /24 scopeglobaleth0 valid_lftforeverpreferred_lftforever inet6fe80::42:aff:fe0a:1d02 /64 scopelink valid_lftforeverpreferred_lftforever root@374417e9ce5b:/ #ping10.10.92.2 PING10.10.92.2(10.10.92.2)56(84)bytesofdata. 64bytesfrom10.10.92.2:icmp_seq=1ttl=60 time =0.657ms 64bytesfrom10.10.92.2:icmp_seq=2ttl=60 time =0.487ms ....... root@374417e9ce5b:/ #pingwww.baidu.com PINGwww.a.shifen.com(115.239.210.27)56(84)bytesofdata. 64bytesfrom115.239.210.27(115.239.210.27):icmp_seq=1ttl=48 time =11.7ms 64bytesfrom115.239.210.27(115.239.210.27):icmp_seq=2ttl=48 time =12.4ms ....... 发现,在两个宿主机的容器内,互相 ping 对方容器的ip,是可以 ping 通的!也可以直接连接外网(桥接模式) 查看两台宿主机的网卡信息,发现docker0虚拟网卡的ip(相当于容器的网关)也已经变成了flannel配置的ip段,并且多了flannel0的虚拟网卡信息 [root@node1~] #ifconfig docker0:flags=4163<UP,BROADCAST,RUNNING,MULTICAST>mtu1472 inet10.10.92.1netmask255.255.255.0broadcast0.0.0.0 inet6fe80::42:ebff:fe16:438dprefixlen64scopeid0x20<link> ether02:42:eb:16:43:8dtxqueuelen0(Ethernet) RXpackets5944bytes337155(329.2KiB) RXerrors0dropped0overruns0frame0 TXpackets6854bytes12310552(11.7MiB) TXerrors0dropped0overruns0carrier0collisions0 eno16777984:flags=4163<UP,BROADCAST,RUNNING,MULTICAST>mtu1500 inet10.10.172.201netmask255.255.255.0broadcast10.10.172.255 inet6fe80::250:56ff:fe86:2135prefixlen64scopeid0x20<link> ether00:50:56:86:21:35txqueuelen1000(Ethernet) RXpackets98110bytes134147911(127.9MiB) RXerrors0dropped0overruns0frame0 TXpackets60177bytes5038428(4.8MiB) TXerrors0dropped0overruns0carrier0collisions0 flannel0:flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>mtu1472 inet10.10.92.0netmask255.255.0.0destination10.10.92.0 unspec00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00txqueuelen500(UNSPEC) RXpackets2bytes168(168.0B) RXerrors0dropped0overruns0frame0 TXpackets2bytes168(168.0B) TXerrors0dropped0overruns0carrier0collisions0 ....... 通过下面命令,可以查看到本机的容器的ip所在的范围 [root@node1~] #psaux|grepdocker|grep"bip" root165890.31.373491227840?Ssl13:230:04 /usr/bin/dockerd-current --add-runtimedocker-runc= /usr/libexec/docker/docker-runc-current --default-runtime=docker-runc-- exec -optnative.cgroupdriver=systemd--userland-proxy-path= /usr/libexec/docker/docker-proxy-current --selinux-enabled--log-driver=journald--signature-verification= false --bip=10.10.92.1 /24 --ip-masq= true --mtu=1472 这里面的“--bip=10.10.92.1 /24 ”这个参数,它限制了所在节点容器获得的IP范围。 这个IP范围是由Flannel自动分配的,由Flannel通过保存在Etcd服务中的记录确保它们不会重复。 [root@node2~] #ifconfig docker0:flags=4163<UP,BROADCAST,RUNNING,MULTICAST>mtu1472 inet10.10.29.1netmask255.255.255.0broadcast0.0.0.0 inet6fe80::42:42ff:fe21:d694prefixlen64scopeid0x20<link> ether02:42:42:21:d6:94txqueuelen0(Ethernet) RXpackets644697bytes41398904(39.4MiB) RXerrors0dropped0overruns0frame0 TXpackets675608bytes1683878582(1.5GiB) TXerrors0dropped0overruns0carrier0collisions0 eth0:flags=4163<UP,BROADCAST,RUNNING,MULTICAST>mtu1500 inet10.10.172.202netmask255.255.255.0broadcast10.10.172.255 inet6fe80::250:56ff:fe86:6833prefixlen64scopeid0x20<link> ether00:50:56:86:68:33txqueuelen1000(Ethernet) RXpackets2552698bytes2441204870(2.2GiB) RXerrors0dropped104overruns0frame0 TXpackets1407162bytes3205869301(2.9GiB) TXerrors0dropped0overruns0carrier0collisions0 flannel0:flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>mtu1472 inet10.10.29.0netmask255.255.0.0destination10.10.29.0 unspec00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00txqueuelen500(UNSPEC) RXpackets2bytes168(168.0B) RXerrors0dropped0overruns0frame0 TXpackets2bytes168(168.0B) TXerrors0dropped0overruns0carrier0collisions0 ....... [root@node2~] #psaux|grepdocker|grep"bip" root319250.31.774740435864?Ssl13:210:05 /usr/bin/dockerd-current --add-runtimedocker-runc= /usr/libexec/docker/docker-runc-current --default-runtime=docker-runc-- exec -optnative.cgroupdriver=systemd--userland-proxy-path= /usr/libexec/docker/docker-proxy-current --selinux-enabled--log-driver=journald--signature-verification= false --bip=10.10.29.1 /24 --ip-masq= true --mtu=1472 本文转自 dengaosky 51CTO博客,原文链接:xxxxhttp://blog.51cto.com/dengaosky/2069377xxx,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android 数据库升级解决方案

请考虑如下情况: 在数据库升级时,不同版本的数据库,他们定义的表结构完全可能是不一样的,比如V1.0的表A有10个column,而在V1.1的表A有12个colum,在升级时,表A增加了两列,此时我们应该怎么做呢。 总体思路 1,将表A重命名,改了A_temp。 2,创建新表A。 3,将表A_temp的数据插入到表A。 下面代码列出了更新表的实现,upgradeTables,给定表名,更新的列名,就可以实现数据库表的更新。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 /** * Upgrade tables. In this method, the sequence is: * <b> * <p>[1] Rename the specified table as a temporary table. * <p>[2] Create a new table which name is the specified name. * <p>[3] Insert data into the new created table, data from the temporary table. * <p>[4] Drop the temporary table. * </b> * * @param db The database. * @param tableName The table name. * @param columns The columns range, format is "ColA, ColB, ColC, ... ColN"; */ protected void upgradeTables(SQLiteDatabase db, String tableName, String columns) { try { db.beginTransaction(); // 1, Rename table. String tempTableName = tableName + "_temp" ; String sql = "ALTER TABLE " + tableName + " RENAME TO " + tempTableName; execSQL(db, sql, null ); // 2, Create table. onCreateTable(db); // 3, Load data sql = "INSERT INTO " + tableName + " (" + columns + ") " + " SELECT " + columns + " FROM " + tempTableName; execSQL(db, sql, null ); // 4, Drop the temporary table. execSQL(db, "DROP TABLE IF EXISTS " + tempTableName, null ); db.setTransactionSuccessful(); } catch (SQLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { db.endTransaction(); } } 得到数据库表的列名 我们可以通过SQL表得到表的列名。 这里需要注意的一点,int columnIndex = c.getColumnIndex("name"); 这里根据name去取得index。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 protected String[] getColumnNames(SQLiteDatabase db, String tableName) { String[] columnNames = null ; Cursor c = null ; try { c = db.rawQuery( "PRAGMA table_info(" + tableName + ")" , null ); if ( null != c) { int columnIndex = c.getColumnIndex( "name" ); if (- 1 == columnIndex) { return null ; } int index = 0 ; columnNames = new String[c.getCount()]; for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) { columnNames[index] = c.getString(columnIndex); index++; } } } catch (Exception e) { e.printStackTrace(); } finally { closeCursor(c); } return columnNames; } upgradeTables方法应该是在onUpgrade方法中去调用。 数据库升级的意义 在应用程序开发的过程中,数据库的升级是一个很重要的组成部分(如果用到了数据库),因为程序可能会有V1.0,V2.0,当用户安装新版本的程序后,必须要保证用户数据不能丢失,对于数据库设计,如果发生变更(如多添加一张表,表的字段增加或减少等),那么我们必须想好数据库的更新策略。 1,定义数据库版本 数据库的版本是一个整型值,在创建SQLiteOpenHelper时,会传入该数据库的版本,如果传入的数据库版本号比数据库文件中存储的版本号大的话,那么SQLiteOpenHelper#onUpgrade()方法就会被调用,我们的升级应该在该方法中完成。 2,如何写升级逻辑 假如我们开发的程序已经发布了两个版本:V1.0,V1.2,我们正在开发V1.3。每一版的数据库版本号分别是18,19,20。 对于这种情况,我们应该如何实现升级? 用户的选择有: 1)V1.0 -> V1.3 DB 18 -> 20 2)V1.1 -> V1.3 DB 19 -> 20 3,注意 数据库的每一个版本所代表的数据库必须是定义好的,比如说V18的数据库,它可能只有两张表TableA和TableB,如果V19要添加一张表TableC,如果V20要修改TableC,那么每一个版本所对应的数据库结构如下: V18 ---> TableA, TableB V19 ---> TableA, TableB, TableC V20 ---> TableA, TableB, TableC (变更) onUpgrade()方法的实现如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 // Pattern for upgrade blocks: // // if (upgradeVersion == [the DATABASE_VERSION you set] - 1){ // .. your upgrade logic.. // upgradeVersion = [the DATABASE_VERSION you set] // } public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { int upgradeVersion = oldVersion; if ( 18 == upgradeVersion) { // Create table C String sql = "CREATE TABLE ..." ; db.execSQL(sql); upgradeVersion = 19 ; } if ( 20 == upgradeVersion) { // Modify table C upgradeVersion = 20 ; } if (upgradeVersion != newVersion) { // Drop tables db.execSQL( "DROP TABLE IF EXISTS " + tableName); // Create tables onCreate(db); } } 从上面的代码可以看到,我们在onUpgrade()方法中,处理了数据库版本从18 -> 20的升级过程,这样做的话,不论用户从18 -> 20,还是从19 -> 20,最终程序的数据库都能升级到V20所对应的数据库结构。 4,如何保证数据不丢失 这是很重要的一部分,假设要更新TableC表,我们建议的做法是: 1)将TableC重命名为TableC_temp SQL语句可以这样写:ALERT TABLE TableC RENAME TO TableC_temp; 2)创建新的TableC表 3)将数据从TableC_temp中插入到TableC表中 SQL语句可以这样写:INSERT INTO TableC (Col1, Col2, Col3) SELECT (Col1, Col2, Col3) FROM TableC_temp; 经过这三步,TableC就完成了更新,同时,也保留了原来表中的数据。 注意: 在onUpgrade()方法中,删除表时,注意使用事务处理,使得修改能立即反应到数据库文件中。 本文转自java豆子博客园博客,原文链接:http://www.cnblogs.com/error404/p/3738630.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

SAP & Oracle EBS集成解决方案

一.需求分析 SAP和Oracle EBS都是作为全球顶级的的ERP产 品,得到了众多客户的亲耐。然而由于 系统庞大、价格昂贵以及定位不同,客户在实施过程中经常会面临以下困惑: 1.SAP如何实现“线上+线下"闭环流程 SAP用户外延流程设计以及二次开发流程面临挑战。 2.如何梳理业务流程 企业的制度、规则和流程体系大多散落在各个业务系统中,管理和变更这些散落的要素存在难点。 3.如何实现持续流程改进 SAP工作流在流程规划、分析和变更方面,如何更好的满足中国企业 需求。 4.如何实现跨系统应用 企业的业务大多是跨系统的,SAP 本身也不是孤立存在的,也需要与其他系统配合来完成业务。我们需要一个 产品来实现跨系统流程 二.方案实现 H3 BPM针对SAP和Oracle EBS分别开发了专用的适配器——H3 Connector For SAP 和H3 Connector For Oracle EBS。H3 Connector For SAP采用最新SAP NCO 3.0, 将BAPI/RFC/其他自定义函数转换成H3 BizBus能接受的方法。 H3 Oralce Connector采用Webservice与Oracle ESB的API连接。 H3 BPM与SAP、Oracle EBS连通后,可以提供全面的流程支持。 三.方案价值 更低的总拥有成本 降低用户数成本,二次开发以及维护的难度与费用 更直观的数据展现 集成集中的更便于审批决策的数据展现 更佳的用户体验 WEB化,移动化, 符合用户操作 习惯的个性化人机 界面 更优秀的IT架构 建立以SOA为 架构、流程中心、 门户为展现、集成各业务系统的企业基础架构 企业更完整的业务流程 延伸SAP流程,覆盖线 下业务,整合第三方系统实现端到端的业务流程 本文转自 lwl_BPM 51CTO博客,原文链接:http://blog.51cto.com/12438115/1913392,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册