MYSQL连接字符串参数解析(解释)

被迫转到MySQL数据库,发现读取数据库时,tinyint类型的值都被转化为boolean了,这样大于1的值都丢失,变成true了。查阅资料MySQL中无Boolean类型,都是存储为tinyint了,这也无妨,但是读回时不应该都变成boolean啊。网络检索没有解决方案,准备向官方报告bug,细想官方不应该有这样低级错误,先下载Connector/NET源码研究一下,发现其中有TreatTinyAsBoolean这个属性,检索百度无结果,google有几条英文的,看来大家都没有注意到这点,或者说很少用.Net玩 MySQL的。 这样将数据库连接字符串变为这样形式就一切正常了: Database=dbname;Data Source=192.168.1.1;Port=3306;User Id=root;Password=****;Charset=utf8;TreatTinyAsBoolean=false; 顺便把源码中涉及的所有属性都列出来: Server,host, data source, datasource, address, addr, network address: 数据库位置(以上任何关键字均可) Database,initial catalog:数据库名 Port:        socket 端口,默认 3306 ConnectionProtocol,protocol:    连接协议,默认 Sockets PipeName,pipe:        连接管道,默认 MYSQL UseCompression,compress:    连接是否压缩,默认 false AllowBatch:    是否允许一次执行多条SQL语句,默认 true Logging:    是否启用日志,默认 false SharedMemoryName:内存共享的名称,默认 MYSQL UseOldSyntax,old syntax, oldsyntax:是否兼容旧版的语法,默认 false ConnectionTimeout,connection timeout:连接超时等待时间,默认15s DefaultCommandTimeout,command timeout:MySqlCommand 超时时间,默认 30s UserID, uid, username, user name, user:数据库登录帐号 Password,pwd:    登录密码 PersistSecurityInfo:是否保持敏感信息,默认 false Encrypt:已经用 SSL 替代了,默认 false CertificateFile:证书文件(.pfx)格式 CertificatePassword:证书的密码 CertificateStoreLocation:证书的存储位置 CertificateThumbprint:证书指纹 AllowZeroDateTime:日期时间能否为零,默认 false ConvertZeroDateTime:为零的日期时间是否转化为 DateTime.MinValue,默认 false UseUsageAdvisor, usage advisor:是否启用助手,会影响数据库性能,默认 false ProcedureCacheSize,procedure cache, procedurecache:同一时间能缓存几条存储过程,0为禁止,默认 25 UsePerformanceMonitor,userperfmon, perfmon:是否启用性能监视,默认 false IgnorePrepare:    是否忽略 Prepare() 调用,默认 true UseProcedureBodies,procedure bodies:是否检查存储过程体、参数的有效性,默认 true AutoEnlist:    是否自动使用活动的连接,默认 true RespectBinaryFlags:是否响应列上元数据的二进制标志,默认 true TreatTinyAsBoolean:是否将 TINYINT(1) 列视为布尔型,默认 true AllowUserVariables:是否允许 SQL 中出现用户变量,默认 false InteractiveSession,interactive:会话是否允许交互,默认 false FunctionsReturnString:所有服务器函数是否按返回字符串处理,默认 false UseAffectedRows:是否用受影响的行数替代查找到的行数来返回数据,默认 false OldGuids:    是否将 binary(16) 列作为 Guids,默认 false Keepalive:    保持 TCP 连接的秒数,默认0,不保持。 ConnectionLifeTime:连接被销毁前在连接池中保持的最少时间(秒)。默认 0 Pooling:    是否使用线程池,默认 true MinimumPoolSize, min pool size:线程池中允许的最少线程数,默认 0 MaximumPoolSize,max pool size:线程池中允许的最多线程数,默认 100 ConnectionReset:连接过期后是否自动复位,默认 false CharacterSet, charset:向服务器请求连接所使用的字符集,默认:无 TreatBlobsAsUTF8:binary blobs 是否按 utf8 对待,默认 false BlobAsUTF8IncludePattern:列的匹配模式,一旦匹配将按 utf8 处理,默认:无 SslMode:    是否启用 SSL 连接模式,默认:MySqlSslMode.None   from:https://blog.csdn.net/caijing3210/article/details/7205423

docker: Error response from daemon: driver failed programming external connectivity on endpoint lamp

Docker容器做端口映射报错 docker: Error response from daemon: driver failed programming external connectivity on endpoint lamp3 (46b7917c940f7358948e55ec2df69a4dec2c6c7071b002bd374e8dbf0d40022c): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 86 -j DNAT --to-destination 172.17.0.2:80 ! -i docker0: iptables: No chain/target/match by that name. 解决方法 docker服务启动时定义的自定义链DOCKER被清除 重启即可systemctl restart docker ———————————————— 版权声明:本文为CSDN博主「米粥粥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_41545647/article/details/102679560

揭开正则表达式的神秘面纱

[原创文章,转载请保留或注明出处:http://www.regexlab.com/zh/regref.htm] 引言 正则表达式(regular expression)就是用一个“字符串”来描述一个特征,然后去验证另一个“字符串”是否符合这个特征。比如 表达式“ab+” 描述的特征是“一个 'a' 和 任意个 'b' ”,那么 'ab', 'abb', 'abbbbbbbbbb' 都符合这个特征。   正则表达式可以用来:(1)验证字符串是否符合指定特征,比如验证是否是合法的邮件地址。(2)用来查找字符串,从一个长的文本中查找符合指定特征的字符串,比查找固定字符串更加灵活方便。(3)用来替换,比普通的替换更强大。 正则表达式学习起来其实是很简单的,不多的几个较为抽象的概念也很容易理解。之所以很多人感觉正则表达式比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难;另一方面,各种引擎自带的文档一般都要介绍它特有的功能,然而这部分特有的功能并不是我们首先要理解的。 文章中的每一个举例,都可以点击进入到测试页面进行测试。闲话少说,开始。 1. 正则表达式规则 1.1 普通字符 字母、数字、汉字、下划线、以及后边章节中没有特殊定义的标点符号,都是"普通字符"。表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。  举例1:表达式 "c",在匹配字符串 "abcde" 时,匹配结果是:成功;匹配到的内容是:"c";匹配到的位置是:开始于2,结束于3。(注:下标从0开始还是从1开始,因当前编程语言的不同而可能不同)  举例2:表达式 "bcd",在匹配字符串 "abcde" 时,匹配结果是:成功;匹配到的内容是:"bcd";匹配到的位置是:开始于1,结束于4。 1.2 简单的转义字符 一些不便书写的字符,采用在前面加 "\" 的方法。这些字符其实我们都已经熟知了。 表达式 可匹配 \r, \n 代表回车和换行符 \t 制表符 \\ 代表 "\" 本身 还有其他一些在后边章节中有特殊用处的标点符号,在前面加 "\" 后,就代表该符号本身。比如:^, $ 都有特殊意义,如果要想匹配字符串中 "^" 和 "$" 字符,则表达式就需要写成 "\^" 和 "\$"。 表达式 可匹配 \^ 匹配 ^ 符号本身 \$ 匹配 $ 符号本身 \. 匹配小数点(.)本身 这些转义字符的匹配方法与 "普通字符" 是类似的。也是匹配与之相同的一个字符。  举例1:表达式 "\$d",在匹配字符串 "abc$de" 时,匹配结果是:成功;匹配到的内容是:"$d";匹配到的位置是:开始于3,结束于5。 1.3 能够与 '多种字符' 匹配的表达式 正则表达式中的一些表示方法,可以匹配 '多种字符' 其中的任意一个字符。比如,表达式 "\d" 可以匹配任意一个数字。虽然可以匹配其中任意字符,但是只能是一个,不是多个。这就好比玩扑克牌时候,大小王可以代替任意一张牌,但是只能代替一张牌。 表达式 可匹配 \d 任意一个数字,0~9 中的任意一个 \w 任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个 \s 包括空格、制表符、换页符等空白字符的其中任意一个 . 小数点可以匹配除了换行符(\n)以外的任意一个字符  举例1:表达式 "\d\d",在匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"12";匹配到的位置是:开始于3,结束于5。  举例2:表达式 "a.\d",在匹配 "aaa100" 时,匹配的结果是:成功;匹配到的内容是:"aa1";匹配到的位置是:开始于1,结束于4。 1.4 自定义能够匹配 '多种字符' 的表达式 使用方括号 [ ] 包含一系列字符,能够匹配其中任意一个字符。用 [^ ] 包含一系列字符,则能够匹配其中字符之外的任意一个字符。同样的道理,虽然可以匹配其中任意一个,但是只能是一个,不是多个。 表达式 可匹配 [ab5@] 匹配 "a" 或 "b" 或 "5" 或 "@" [^abc] 匹配 "a","b","c" 之外的任意一个字符 [f-k] 匹配 "f"~"k" 之间的任意一个字母 [^A-F0-3] 匹配 "A"~"F","0"~"3" 之外的任意一个字符  举例1:表达式 "[bcd][bcd]" 匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"bc";匹配到的位置是:开始于1,结束于3。  举例2:表达式 "[^abc]" 匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"1";匹配到的位置是:开始于3,结束于4。 1.5 修饰匹配次数的特殊符号 前面章节中讲到的表达式,无论是只能匹配一种字符的表达式,还是可以匹配多种字符其中任意一个的表达式,都只能匹配一次。如果使用表达式再加上修饰匹配次数的特殊符号,那么不用重复书写表达式就可以重复匹配。 使用方法是:"次数修饰"放在"被修饰的表达式"后边。比如:"[bcd][bcd]" 可以写成 "[bcd]{2}"。 表达式 作用 {n} 表达式重复n次,比如: "\w{2}" 相当于 "\w\w"; "a{5}" 相当于 "aaaaa" {m,n} 表达式至少重复m次,最多重复n次,比如: "ba{1,3}"可以匹配 "ba"或"baa"或"baaa" {m,} 表达式至少重复m次,比如: "\w\d{2,}"可以匹配 "a12","_456","M12344"… ? 匹配表达式0次或者1次,相当于 {0,1},比如: "a[cd]?"可以匹配 "a","ac","ad" + 表达式至少出现1次,相当于 {1,},比如: "a+b"可以匹配 "ab","aab","aaab"… * 表达式不出现或出现任意次,相当于 {0,},比如: "\^*b"可以匹配 "b","^^^b"…  举例1:表达式 "\d+\.?\d*" 在匹配 "It costs $12.5" 时,匹配的结果是:成功;匹配到的内容是:"12.5";匹配到的位置是:开始于10,结束于14。  举例2:表达式 "go{2,8}gle" 在匹配 "Ads by goooooogle" 时,匹配的结果是:成功;匹配到的内容是:"goooooogle";匹配到的位置是:开始于7,结束于17。 1.6 其他一些代表抽象意义的特殊符号 一些符号在表达式中代表抽象的特殊意义: 表达式 作用 ^ 与字符串开始的地方匹配,不匹配任何字符 $ 与字符串结束的地方匹配,不匹配任何字符 \b 匹配一个单词边界,也就是单词和空格之间的位置,不匹配任何字符 进一步的文字说明仍然比较抽象,因此,举例帮助大家理解。  举例1:表达式 "^aaa" 在匹配 "xxx aaa xxx" 时,匹配结果是:失败。因为 "^" 要求与字符串开始的地方匹配,因此,只有当 "aaa" 位于字符串的开头的时候,"^aaa" 才能匹配, 比如:"aaa xxx xxx"。  举例2:表达式 "aaa$" 在匹配 "xxx aaa xxx" 时,匹配结果是:失败。因为 "$" 要求与字符串结束的地方匹配,因此,只有当 "aaa" 位于字符串的结尾的时候,"aaa$" 才能匹配, 比如:"xxx xxx aaa"。  举例3:表达式 ".\b." 在匹配 "@@@abc" 时,匹配结果是:成功;匹配到的内容是:"@a";匹配到的位置是:开始于2,结束于4。 进一步说明:"\b" 与 "^" 和 "$" 类似,本身不匹配任何字符,但是它要求它在匹配结果中所处位置的左右两边,其中一边是 "\w" 范围,另一边是 非"\w" 的范围。  举例4:表达式 "\bend\b" 在匹配 "weekend,endfor,end" 时,匹配结果是:成功;匹配到的内容是:"end";匹配到的位置是:开始于15,结束于18。 一些符号可以影响表达式内部的子表达式之间的关系: 表达式 作用 | 左右两边表达式之间 "或" 关系,匹配左边或者右边 ( ) (1). 在被修饰匹配次数的时候,括号中的表达式可以作为整体被修饰 (2). 取匹配结果的时候,括号中的表达式匹配到的内容可以被单独得到  举例5:表达式 "Tom|Jack" 在匹配字符串 "I’m Tom, he is Jack" 时,匹配结果是:成功;匹配到的内容是:"Tom";匹配到的位置是:开始于4,结束于7。匹配下一个时,匹配结果是:成功;匹配到的内容是:"Jack";匹配到的位置时:开始于15,结束于19。  举例6:表达式 "(go\s*)+" 在匹配 "Let’s go go go!" 时,匹配结果是:成功;匹配到内容是:"go go go";匹配到的位置是:开始于6,结束于14。  举例7:表达式 "¥(\d+\.?\d*)" 在匹配 "$10.9,¥20.5" 时,匹配的结果是:成功;匹配到的内容是:"¥20.5";匹配到的位置是:开始于6,结束于10。单独获取括号范围匹配到的内容是:"20.5"。 2. 正则表达式中的一些高级规则 2.1 匹配次数中的贪婪与非贪婪 在使用修饰匹配次数的特殊符号时,有几种表示方法可以使同一个表达式能够匹配不同的次数,比如:"{m,n}", "{m,}", "?", "*", "+",具体匹配的次数随被匹配的字符串而定。这种重复匹配不定次数的表达式在匹配过程中,总是尽可能多的匹配。比如,针对文本 "dxxxdxxxd",举例如下: 表达式 匹配结果  (d)(\w+) "\w+" 将匹配第一个 "d" 之后的所有字符 "xxxdxxxd"  (d)(\w+)(d) "\w+" 将匹配第一个 "d" 和最后一个 "d" 之间的所有字符 "xxxdxxx"。虽然 "\w+" 也能够匹配上最后一个 "d",但是为了使整个表达式匹配成功,"\w+" 可以 "让出" 它本来能够匹配的最后一个 "d" 由此可见,"\w+" 在匹配的时候,总是尽可能多的匹配符合它规则的字符。虽然第二个举例中,它没有匹配最后一个 "d",但那也是为了让整个表达式能够匹配成功。同理,带 "*" 和 "{m,n}" 的表达式都是尽可能地多匹配,带 "?" 的表达式在可匹配可不匹配的时候,也是尽可能的 "要匹配"。这 种匹配原则就叫作 "贪婪" 模式 。 非贪婪模式: 在修饰匹配次数的特殊符号后再加上一个 "?" 号,则可以使匹配次数不定的表达式尽可能少的匹配,使可匹配可不匹配的表达式,尽可能的 "不匹配"。这种匹配原则叫作 "非贪婪" 模式,也叫作 "勉强" 模式。如果少匹配就会导致整个表达式匹配失败的时候,与贪婪模式类似,非贪婪模式会最小限度的再匹配一些,以使整个表达式匹配成功。举例如下,针对文本 "dxxxdxxxd" 举例: 表达式 匹配结果  (d)(\w+?) "\w+?" 将尽可能少的匹配第一个 "d" 之后的字符,结果是:"\w+?" 只匹配了一个 "x"  (d)(\w+?)(d) 为了让整个表达式匹配成功,"\w+?" 不得不匹配 "xxx" 才可以让后边的 "d" 匹配,从而使整个表达式匹配成功。因此,结果是:"\w+?" 匹配 "xxx" 更多的情况,举例如下:  举例1:表达式 "<td>(.*)</td>" 与字符串 "<td><p>aa</p></td> <td><p>bb</p></td>" 匹配时,匹配的结果是:成功;匹配到的内容是 "<td><p>aa</p></td> <td><p>bb</p></td>" 整个字符串, 表达式中的 "</td>" 将与字符串中最后一个 "</td>" 匹配。  举例2:相比之下,表达式 "<td>(.*?)</td>" 匹配举例1中同样的字符串时,将只得到 "<td><p>aa</p></td>", 再次匹配下一个时,可以得到第二个 "<td><p>bb</p></td>"。 2.2 反向引用 \1, \2… 表达式在匹配时,表达式引擎会将小括号 "( )" 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候,小括号包含的表达式所匹配到的字符串可以单独获取。这一点,在前面的举例中,已经多次展示了。在实际应用场合中,当用某种边界来查找,而所要获取的内容又不包含边界时,必须使用小括号来指定所要的范围。比如前面的 "<td>(.*?)</td>"。 其实,"小括号包含的表达式所匹配到的字符串" 不仅是在匹配结束后才可以使用,在匹配过程中也可以使用。表达式后边的部分,可以引用前面 "括号内的子匹配已经匹配到的字符串"。引用方法是 "\" 加上一个数字。"\1" 引用第1对括号内匹配到的字符串,"\2" 引用第2对括号内匹配到的字符串……以此类推,如果一对括号内包含另一对括号,则外层的括号先排序号。换句话说,哪一对的左括号 "(" 在前,那这一对就先排序号。 举例如下:  举例1:表达式 "('|")(.*?)(\1)" 在匹配 " 'Hello', "World" " 时,匹配结果是:成功;匹配到的内容是:" 'Hello' "。再次匹配下一个时,可以匹配到 " "World" "。  举例2:表达式 "(\w)\1{4,}" 在匹配 "aa bbbb abcdefg ccccc 111121111 999999999" 时,匹配结果是:成功;匹配到的内容是 "ccccc"。再次匹配下一个时,将得到 999999999。这个表达式要求 "\w" 范围的字符至少重复5次, 注意与 "\w{5,}" 之间的区别。  举例3:表达式 "<(\w+)\s*(\w+(=('|").*?\4)?\s*)*>.*?</\1>" 在匹配 "<td id=’td1′ style="bgcolor:white"></td>" 时,匹配结果是成功。如果 "<td>" 与 "</td>" 不配对,则会匹配失败;如果改成其他配对,也可以匹配成功。 2.3 预搜索,不匹配;反向预搜索,不匹配 前面的章节中,我讲到了几个代表抽象意义的特殊符号:"^","$","\b"。它们都有一个共同点,那就是:它们本身不匹配任何字符,只是对 "字符串的两头" 或者 "字符之间的缝隙" 附加了一个条件。理解到这个概念以后,本节将继续介绍另外一种对 "两头" 或者 "缝隙" 附加条件的,更加灵活的表示方法。 正向预搜索:"(?=xxxxx)","(?!xxxxx)" 格式:"(?=xxxxx)",在被匹配的字符串中,它对所处的 "缝隙" 或者 "两头" 附加的条件是:所在缝隙的右侧,必须能够匹配上 xxxxx 这部分的表达式。因为它只是在此作为这个缝隙上附加的条件,所以它并不影响后边的表达式去真正匹配这个缝隙之后的字符。这就类似 "\b",本身不匹配任何字符。"\b" 只是将所在缝隙之前、之后的字符取来进行了一下判断,不会影响后边的表达式来真正的匹配。  举例1:表达式 "Windows (?=NT|XP)" 在匹配 "Windows 98, Windows NT, Windows 2000" 时,将只匹配 "Windows NT" 中的 "Windows ",其他的 "Windows " 字样则不被匹配。  举例2:表达式 "(\w)((?=\1\1\1)(\1))+" 在匹配字符串 "aaa ffffff 999999999" 时,将可以匹配6个"f"的前4个,可以匹配9个"9"的前7个。这个表达式可以读解成:重复4次以上的字母数字,则匹配其剩下最后2位之前的部分。当然,这个表达式可以不这样写,在此的目的是作为演示之用。 格式:"(?!xxxxx)",所在缝隙的右侧,必须不能匹配 xxxxx […]

vue中加载loading

首先在components文件夹中新建一个loading.vue组件:   1.loading.vue组件内容如下:

  css代码:

   2.app.vue中设置:

  3.在main.js中设置  

  4.在.vue组件中使用

  效果如下:   from:https://blog.csdn.net/liangmengbk/article/details/90201596

Unknown instruction: FROM CENTOS:7

用Dockerfile构建jdk镜像的时候出的错 把Dockerfile文件删除之后重新建一个 把空格 符号全更换一遍英文 最后运行成功   from:https://blog.csdn.net/weixin_43555477/article/details/106480089

vue中引用vant,附带样式

1、首先 npm install babel-plugin-import 和 npm install vant 2、样式在项目中的  .babelrc 文件下 ["import", {"libraryName": "vant","libraryDirectory": "es","style": true}, "vant"]]  //vant样式引用 3、在main.js中 import { Button } from 'vant'   //引用vant组件库中可用组件 Vue.use(Button )  注册组件即可。 from:https://www.cnblogs.com/1rookie/p/12660684.html

ASP.NET quartz 定时任务

1.下载 2.使用例子 Demo 概述:Quartz 是开源的定时任务工具类,默认每隔10秒执行一次任务,相当于C#的Timer,不断的循环执行(Start 方法),也可以随时停止(ShutDown方法)。 一 下载 下载地址:quartz     二 使用例子 Demo 1)引入程序集,必须引入三个,不然报错 2)IScheduler 和 IJob

3)每隔10秒,修改一次缓存的值,可以打断点随时查看缓存里的实时值。 from:https://www.cnblogs.com/ligenyun/p/7729989.html

还在傻傻分不清ES5、Es6数组方法?各大姿势来袭

前言 初衷: 在面试中,面试官经常问到说一下Es5和Es6的数组方法有哪些,有很多同学老是分不清楚,今天笔者就来分享一下。 适合人群: 前端初级开发 Es5系列 indexOf 用途: 用于查找数组中是否存在某个值,如果存在则返回某个值的下标,否则返回-1

map 用途: map是一个数组函数方法,接收三个参数,value,index,self,返回值是处理完的结果。

forEach 用途: 用于遍历一个数组,接收三个参数,value,index,self,返回值为undefined

splice 用途: 用于数组删除或替换内容,接收三个参数: 第一个参数是,删除或添加的位置 第二个参数是,要删除的几位,如果为0则不删除 第三个参数是,向数组添加内容

slice 用途: 用于截取数组值,接收两个参数,第一个参数是要获取哪个值的下标,第二个参数是截取到哪个下标的前一位。

filter 用途: 用于过滤数组内的符合条件的值,返回值为满足条件的数组对象

every **用途:**用于检测数组所有元素是否都符合指定条件,返回值为Boolean , 该方法是数组中必须全部值元素满足条件返回true,否则false

some 用途: 用于检测数组中的元素是否满足指定条件,返回值为Boolean , 该方法是只要数组中有一项满足条件就返回true,否则false

reduce 用途: 该方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。该方法回调函数接收四个参数 第一个参数:初始值, 或者计算结束后的返回值 第二个参数:当前元素 第二个参数:当前元素的索引 第四个参数:当前元素所属的数组对象,本身 我们一般只用前两个就行,reduce第一个参数回调函数,第二个参数是初始值

reverse 用途: 用于数组反转

join 用途: 用于数据以什么形式拼接

sort 用途: 用于将数组排序,排序规则看返回值 返回值为正数,后面的数在前面 返回值为负数,前面的数不变,还在前面 返回值为0,都不动

concat 用途: 用于合并数组原始

push 用途: 向数组后面添加元素,返回值为数组的length

pop 用途: 用于删除数组尾部的元素,返回值为删除的元素

shift 用途: 用于删除数组的头部,返回值为删除的元素

unshift 用途: 向数组的头部添加元素,返回值为数组的length

toString 用途: 用于将数组内容转换为字符串

Es6 + includes 用途: 检测数组中是否存在该元素,返回Boolean值

find 用途: 查找数组的元素,满足条件的返回单个值,按照就近原则返回

findIndex 用途: 查找数组中元素,满足条件的返回数组下标

flat 用途: 用于拉平嵌套数组对象

fill 用途: 用于填充数组对象

Array.isArray 用途: 检测对象是不是一个数组

Array.from 用途: 将伪数组转换为真数组

Array.of 用途: 用于生成一个数组对象,主要是用来弥补Array()的不足

改变原始数组值的有哪些 splice、reverse、sort、push、pop、shift、unshift、fill 结语 这里keys、values、entries就不写啦,它们使用数组方式的话,返回的是Iterator遍历器对象。欢迎大家查漏补缺常用数组方法哦   from:https://zhuanlan.zhihu.com/p/361204051

服务注册与发现的原理和实现

什么是服务注册发现? 对于搞微服务的同学来说,服务注册、服务发现的概念应该不会太陌生。 简单来说,当服务A需要依赖服务B时,我们就需要告诉服务A,哪里可以调用到服务B,这就是服务注册发现要解决的问题。 Service B 把自己注册到 Service Registry 叫做 服务注册 Service A 从 Service Registry 发现 Service B 的节点信息叫做 服务发现 服务注册 服务注册是针对服务端的,服务启动后需要注册,分为几个部分: 启动注册 定时续期 退出撤销 启动注册 当一个服务节点起来之后,需要把自己注册到 Service Registry 上,便于其它节点来发现自己。注册需要在服务启动完成并可以接受请求时才会去注册自己,并且会设置有效期,防止进程异常退出后依然被访问。 定时续期 定时续期相当于 keep alive,定期告诉 Service Registry 自己还在,能够继续服务。 退出撤销 当进程退出时,我们应该主动去撤销注册信息,便于调用方及时将请求分发到别的节点。同时,go-zero 通过自适应的负载均衡来保证即使节点退出没有主动注销,也能及时摘除该节点。 服务发现 服务发现是针对调用端的,一般分为两类问题: 存量获取 增量侦听 还有一个常见的工程问题是 应对服务发现故障 当服务发现服务(比如 etcd, consul, nacos等)出现问题的时候,我们不要去修改已经获取到的 endpoints 列表,从而可以更好的确保 etcd 等宕机后所依赖的服务依然可以正常交互。 存量获取 当 Service A 启动时,需要从 Service Registry 获取 Service B 的已有节点列表:Service B1, Service B2, Service B3,然后根据自己的负载均衡算法来选择合适的节点发送请求。 增量侦听 上图已经有了 Service B1, Service B2, Service B3,如果此时又启动了 Service B4,那么我们就需要通知 Service A 有个新增的节点。如图: 应对服务发现故障 对于服务调用方来说,我们都会在内存里缓存一个可用节点列表。不管是使用 etcd,consul 或者 nacos 等,我们都可能面临服务发现集群故障,以 etcd 为例,当遇到 etcd 故障时,我们就需要冻结 Service B 的节点信息而不去变更,此时一定不能去清空节点信息,一旦清空就无法获取了,而此时 Service B 的节点很可能都是正常的,并且 go-zero 会自动隔离和恢复故障节点。 服务注册、服务发现的基本原理大致如此,当然实现起来还是比较复杂的,接下来我们一起看看 go-zero 里支持哪些服务发现的方式。 go-zero 之内置服务发现 go-zero 默认支持三种服务发现方式: 直连 基于 etcd 的服务发现 基于 kubernetes endpoints 的服务发现 直连 直连是最简单的方式,当我们的服务足够简单时,比如单机即可承载我们的业务,我们可以直接只用这种方式。 在 rpc 的配置文件里直接指定 endpoints 即可,比如:

  zrpc 调用端就会分配负载到这两个节点上,其中一个节点有问题时 zrpc 会自动摘除,等节点恢复时会再次分配负载。 这个方法的缺点是不能动态增加节点,每次新增节点都需要修改调用方配置并重启。 基于 etcd 的服务发现 当我们的服务有一定规模之后,因为一个服务可能会被很多个服务依赖,我们就需要能够动态增减节点,而无需修改很多的调用方配置并重启。 常见的服务发现方案有 etcd, consul, nacos 等。 go-zero内置集成了基于 etcd 的服务发现方案,具体使用方法如下:

  Hosts 是 etcd 集群地址 Key 是服务注册上去的 key 基于 Kubernetes Endpoints 的服务发现 如果我们的服务都是部署在 Kubernetes 集群上的话,Kubernetes 本身是通过自带的 etcd 管理集群状态的,所有的服务都会把自己的节点信息注册到 Endpoints 对象,我们可以直接给 deployment 权限去读取集群的 Endpoints 对象即可获得节点信息。 Service B 的每个 Pod 启动时,会将自己注册到集群的 Endpoints 里 Service A 的每个 Pod 启动时,可以从集群的 Endpoints 里获取 Service B 的节点信息 当 Service B 的节点发生改变时,Service A 可以通过 watch 集群的 Endpoints 感知到 在这个机制工作之前,我们需要配置好当前 namespace 内 pod 对集群 Endpoints 访问权限,这里有三个概念: ClusterRole 定义集群范围的权限角色,不受 namespace 控制 ServiceAccount 定义 namespace 范围内的 service account ClusterRoleBinding 将定义好的 ClusterRole 和不同 namespace 的 ServiceAccount 进行绑定 具体的 Kubernetes 配置文件可以参考 这里,其中 namespace 按需修改。 注意:当启动时报没有权限获取 Endpoints 时记得检查这些配置有没落实 :) zrpc 的基于 Kubernetes Endpoints 的服务发现使用方法如下:

  其中: mynamespace:被调用的 rpc 服务所在的 namespace myservice:被调用的 rpc 服务的名字 3456:被调用的 rpc 服务的端口 在创建 deployment 配置文件时一定要加上 serviceAccountName 来指定使用哪个 ServiceAccount,示例如下:

  注意其中 serviceAccountName 指定该 deployment 创建出来的 pod 用哪个 ServiceAccount。 server 和 client 都部署到 Kubernetes 集群里之后可以通过以下命令滚动重启所有 server 节点

  利用如下命令查看 client 节点日志:

  可以看到我们的服务发现机制完美跟进了 server 节点的变化,并且在服务更新期间没有出现异常请求。 完整代码示例见 https://github.com/zeromicro/zero-examples/tree/main/discovery/k8s 下一篇文章我将讲解在 go-zero 里如何实现基于 consul, nacos 等的服务注册发现,敬请期待! 项目地址 https://github.com/tal-tech/go-zero https://gitee.com/kevwan/go-zero 欢迎使用 go-zero 并 star 支持我们! 微信交流群 关注『微服务实践』公众号并点击 交流群 获取社区群二维码。   from:https://my.oschina.net/kevwan/blog/5259846

服务的注册与发现(Consul、zookeeper、etcd、eureka、Nacos)

一. 对比常用的注册中心 Consul、zookeeper、etcd、eureka、Nacos Feature Consul Zookeeper Etcd Eureka Nacos 服务健康检查  服务状态,内存,硬盘等  (弱)长连接,keepalive  连接心跳  可配支持 传输层 (PING 或 TCP)和应用层 (如 HTTP、MySQL、用户自定义)的健康检查 多数据中心  支持  —  —  — 支持 kv存储服务  支持  支持  支持  —  支持 一致性   Raft  Paxos   Raft  — Raft CAP定理  CP  CP  CP  AP CP: 配置中心 AP: 注册中心 使用接口 (多语言能力)  支持http和dns  客户端  http/grpc  http(sidecar) Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用 原生SDK、OpenAPI、或一个独立的Agent watch支持  全量/支持long polling  支持  支持 long polling 支持 long polling/大部分增量 支持 long polling/大部分增量 自身监控  metrics  —  metrics  metrics   安全  acl /https  acl  https支持(弱)  — acl Spring Cloud集成  已支持  已支持  已支持  已支持  已支持 备注 可以作为eureka的替代使用     2.0不在更新 1. 支持dubbo 2. spring-cloud-alibaba支持 二. 个人总结 springcloud中实现的注册中心 1. 当项目数量少于1000时, 可以考虑 eureka 1.x ; 2.0版本官方不在维护 2. 使用最新的可以考虑使用 Consul, 使用Raft实现一致性的同时, 尽量保证可用, 支持 k8s 3. 使用dubbo, 可以使用 zookeeper、 nacos,  推荐使用 nacos 4. nacos是阿里来源的集配置中心和注册中心与一体的, 新版本 AP 支持性能良好, 天然支持 dubbo 在 spring-cloud-alibaba 项目中, 很好的实现配置中心和注册中心 支持 k8s、spring 系列、 docker 和 多注册中心的同步 2.0 规划 屏蔽 同步 k8s 和 spring 管理的差异、 支持 istio 5. 新项目可以使用 nacos   from:https://www.cnblogs.com/lovezbs/p/14244007.html

Nacos – 阿里开源配置中心

配置中心相信大家都有听过,zookeeper、apollo等等都是配置中心的代表,但大部分都是JAVA系为主的,笔者主要开发语言使用的是Golang当然也有类似于ETCD这样的组件,但是并不方便管理也无法可视化,在无意之间发现了阿里爸爸开源了nacos这个服务发现+配置中心组件,也经过了一段时间的时候在这里分享给大家 附上: 喵了个咪的博客:w-blog.cn Nacos官方Git地址:https://github.com/alibaba/nacos Nacos官方文档地址:https://nacos.io/zh-cn/docs/ Go语言SDK地址:https://github.com/sunmi-OS/gocore/tree/master/nacos PS:当前官方最新版本为 V1.1.3,阿里云有提供配置中心服务ACM使用方式和Nacos相同,使用阿里云的前提下免运维是个不错的选择 一、Nacos介绍 Nacos是阿里云中间件团队开源的一个项目,基于阿里云内部提供的ACM配置管理服务进行独立,截止到现在github已经有8K以上的star了,虽然成熟度还不能和携程开源的apollo相提并论,比较也是在阿里云上提供服务的组件稳定性还是值得相信的,当然要使用介绍Nacos必须要介绍介绍配置中心这样一个思想了。 配置中心是个老生常谈的话题,从有软件编程开始配置管理都是工程中重要的一步,当然对与一个单体应用只需要单个配置文件或环境变量的方式来管理配置就好了所以不再本文的讨论范围内,配置中心主要解决服务化或微服务化下的配置管理中的如下问题: 有效的密码管理,开发不碰触密码配置,运维人员和架构团队统一管理避免泄露; 多项目下的配置绝对统一性,不会出现配置写错导致的BUG 对于配置的编辑、存储、分发、变更管理、历史版本管理、变更审计有完善的能力 配置分组和灰度发布 有好处当然也有坏处,相对于使用配置文件我们还需要解决如下问题: 配置中心异常情况下服务怎么保障可用(SDK提供Cache功能当中心服务不可用会使用上一次加载的缓存配置) 配置变更后的程序生效逻辑(SDK提供配置变动订阅逻辑可以订阅配置变动编写处理逻辑) 开发过程中的配置文件调试(需要框架进行设计) 对于部分语言来说(PHP)配置中心性能的问题(Nacos的吞吐量8C16G 15K并发) 对比下来还是可以总结出配置中心利大于弊的结论 二、Nacos部署 Nacos不止支持二进制部署也支持支持Docker和K8S部署,因为Nacos是有状态服务存储的数据需要依赖于Mysql而且集群的方式需要指定slave的IP所以使用K8S并不是很好的选择(K8S使用StatefulSet来运行有状态服务),笔者这里用Docker-Composer的方式来运行Nacos

访问:http://localhost:8848/nacos/ 就可以看到登录界面了 PS:默认用户名和密码都是 nacos 阿里云ACM服务 当然自己部署Nacos还会面临很多挑战,比如: 集群搭建 稳定性 Mysql数据库维护 配置安全保护(Nacos没有密码一说,但是ACM需要使用阿里云的密钥可以提高安全程度) PS:秉着能用服务就不自己搭建的原则笔者最终使用的是阿里云的ACM服务(当前ACM服务免费) PS:需要注意阿里云ACM和Nacos在SDK中的链接方式有不同 三、基础使用 Nacos有几个基础概念,我们只有先了解清楚之后才能更好的结合到业务场景: namespace 命名空间 Group 配置分组 DataID 具体的配置名称 一般我们使用namespace来区分不同的项目或环境,Group区分配置的差异系比如A业务获取的配置和B团队的有一些细微的差别可以通过Group来区分,最后使用DataId来区分具体的配置项 增加一个namespace 新增一个配置 支持很多种配置格式,也可以使用自定义的格式甚至直接存放代码都行 也有对应的JAVA系的示例代码 四、SDK和OpenApi使用配置 Nacos支持一下语言的SDK(当然GIT上也有很多非官方的SDK库): Java go cpp python nodejs 大家可以在官方文档中查看具体的使用方式 上面已经配置好的配置我们可以使用OpenApi来访问它

特别注意tenant就是需要输入namespace的名称,但是不是原名是如下的名称 from:https://www.cnblogs.com/cuiyubo/p/11756777.html

微服务之consul(一)

一、概述 consul是google开源的一个使用go语言开发的服务发现、配置管理中心服务。内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等)。服务部署简单,只有一个可运行的二进制的包。每个节点都需要运行agent,他有两种运行模式server和client。每个数据中心官方建议需要3或5个server节点以保证数据安全,同时保证server-leader的选举能够正确的进行。 @client CLIENT表示consul的client模式,就是客户端模式。是consul节点的一种模式,这种模式下,所有注册到当前节点的服务会被转发到SERVER,本身是不持久化这些信息。 @server SERVER表示consul的server模式,表明这个consul是个server,这种模式下,功能和CLIENT都一样,唯一不同的是,它会把所有的信息持久化的本地,这样遇到故障,信息是可以被保留的。 @server-leader 中间那个SERVER下面有LEADER的字眼,表明这个SERVER是它们的老大,它和其它SERVER不一样的一点是,它需要负责同步注册的信息给其它的SERVER,同时也要负责各个节点的健康监测。 @raft server节点之间的数据一致性保证,一致性协议使用的是raft,而zookeeper用的paxos,etcd采用的也是raft。 @服务发现协议 consul采用http和dns协议,etcd只支持http @服务注册 consul支持两种方式实现服务注册,一种是通过consul的服务注册http API,由服务自己调用API实现注册,另一种方式是通过json个是的配置文件实现注册,将需要注册的服务以json格式的配置文件给出。consul官方建议使用第二种方式。 @服务发现 consul支持两种方式实现服务发现,一种是通过http API来查询有哪些服务,另外一种是通过consul agent 自带的DNS(8600端口),域名是以NAME.service.consul的形式给出,NAME即在定义的服务配置文件中,服务的名称。DNS方式可以通过check的方式检查服务。 @服务间的通信协议 Consul使用gossip协议管理成员关系、广播消息到整个集群,他有两个gossip  pool(LAN pool和WAN pool),LAN pool是同一个数据中心内部通信的,WAN pool是多个数据中心通信的,LAN pool有多个,WAN pool只有一个。   二、consul集群搭建 1)安装 首先去官网现在合适的consul包:https://www.consul.io/downloads.html 安装直接下载zip包,解压后只有一个可执行的文件consul,将consul添加到系统的环境变量里面。 #unzip consul_1.2.3_linux_amd64.zip #cp -a consul  /usr/bin #consul

输入consul,出现上面的内容证明安装成功。   2)启动 consul必须启动agent才能使用,有两种启动模式server和client,还有一个官方自带的ui。server用与持久化服务信息,集群官方建议3或5个节点。client只用与于server交互。ui可以查看集群情况的。 server: cn1: #consul agent  -bootstrap-expect 2  -server   -data-dir /data/consul0 -node=cn1 -bind=192.168.1.202 -config-dir /etc/consul.d -enable-script-checks=true  -datacenter=dc1 cn2: #consul agent    -server  -data-dir /data/consul0 -node=cn2 -bind=192.168.1.201 -config-dir /etc/consul.d -enable-script-checks=true  -datacenter=dc1  -join 192.168.1.202 cn3: #consul agent  -server  -data-dir /data/consul0 -node=cn3 -bind=192.168.1.200 -config-dir /etc/consul.d -enable-script-checks=true  -datacenter=dc1  -join 192.168.1.202 参数解释: -bootstrap-expect:集群期望的节点数,只有节点数量达到这个值才会选举leader。 -server: 运行在server模式 -data-dir:指定数据目录,其他的节点对于这个目录必须有读的权限 -node:指定节点的名称 -bind:为该节点绑定一个地址 -config-dir:指定配置文件,定义服务的,默认所有一.json结尾的文件都会读 -enable-script-checks=true:设置检查服务为可用 -datacenter: 数据中心没名称, -join:加入到已有的集群中   client: #consul agent   -data-dir /data/consul0 -node=cn4 -bind=192.168.1.199 -config-dir /etc/consul.d -enable-script-checks=true  -datacenter=dc1  -join 192.168.1.202 client节点可以有多个,自己根据服务指定即可。 ui: #consul agent  -ui  -data-dir /data/consul0 -node=cn4 -bind=192.168.1.198  -client 192.168.1.198   -config-dir /etc/consul.d -enable-script-checks=true  -datacenter=dc1  -join 192.168.1.202 -ui:使用自带的ui, -ui-dir:指定ui的目录,使用自己定义的ui -client:指定web  ui、的监听地址,默认127.0.0.1只能本机访问。 集群创建完成后: 使用一些常用的命令检查集群的状态: #consul  info 可以在raft:stat看到此节点的状态是Fllower或者leader #consul members Node Address Status Type Build Protocol DC Segment cn1 192.168.1.202:8301 alive server 1.0.2 2 dc1 <all> cn2 192.168.1.201:8301 alive server 1.0.2 2 dc1 <all> cn3 192.168.1.200:8301 alive client 1.0.2 2 dc1 <default> 新加入一个节点有几种方式; 1、这种方式,重启后不会自动加入集群 #consul  join  192.168.1.202 2、#在启动的时候使用-join指定一个集群 #consul agent  -ui  -data-dir /data/consul0 -node=cn4 -bind=192.168.1.198 -config-dir /etc/consul.d -enable-script-checks=true  -datacenter=dc1  -join 192.168.1.202 3、使用-startjoin或-rejoin #consul agent  -ui  -data-dir /data/consul0 -node=cn4 -bind=192.168.1.198 -config-dir /etc/consul.d -enable-script-checks=true  -datacenter=dc1  -rejoin   访问ui: http://192.168.1.198:8500/ui 端口: 8300:consul agent服务relplaction、rpc(client-server) 8301:lan gossip 8302:wan gossip 8500:http api端口 8600:DNS服务端口   3)服务注册 采用的是配置文件的方式,(官方推荐)首先创建一个目录用于存放定义服务的配置文件 #mkdir /etc/consul.d/ 启动服务的时候要使用-config-dir 参数指定。 下面给出一个服务定义: #cat web.json

如果这样启动consul后,会发现consul的日志里面一直报错,因为我们没有启动80端口的服务,下面给出我写的一个go程序: #cat  web.go

#需要一个goalong的环境: #go  build -o  web  web.go #./web 此时就可以在没有运行web服务的机器上面执行DNS查询: # dig @127.0.0.1 -p 8600 web.service.consul SRV ;; ANSWER SECTION: web.service.consul. 0 IN SRV 1 1 80 cn2.node.dc1.consul. web.service.consul. 0 IN SRV 1 1 80 cn3.node.dc1.consul. ;; ADDITIONAL SECTION: cn2.node.dc1.consul. 0 IN A 192.168.1.201 cn2.node.dc1.consul. 0 IN TXT "consul-network-segment=" cn3.node.dc1.consul. 0 IN A 192.168.1.200 cn3.node.dc1.consul. 0 IN TXT "consul-network-segment=" ;; Query time: 17 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: 四 1月 04 14:39:32 CST 2018 ;; MSG SIZE rcvd: 229 可以看到服务已经注册到集群里面了。 使用dns查询,默认域名格式NAME.service.consul,NAME就是web.json里面定义的service的name。可以自己指定域和端口:-domain、-dns-port 53 为了方便使用consul集群的注册使用,所以写了一个三节点client的注册脚本,方便统一注册服务和管理。还利用到了nfs,将服务文件共享到集群。

hosts是client节点列表。可以只注册其中的一个节点,输入hosts中对应的key,也可以输入all,注册到所有节点;nfs共享的是/etc/consul.d目录。 4)健康检查 check使用来做服务的健康检查的,可以拥有多个,也可以不使用支持多种方式检查。check必须是script或者TTL类型,如果是TTL类型则ttl变量必须被提供。script是consul主动去检查服务的健康状况,ttl是服务主动向consul报告自己的状况。新版本的consul不在使用script来表示,使用args,如果是https服务的健康检查,可以使用args这种脚本的方式实现,因为consul默认不支持https的健康检查。 script check: "check": { "args": ["/data/scripts/kubeadm-ha-0.sh",""],     "interval": "10s" }   http check: { "check": { "id": "api", "name": "HTTP API  500", "http": "http://loclhost:500/health", "interval": "10s", "timeout": "1s" } }   tcp  check: { "check": { "id": "ssh", "name": "ssh TCP 26622", "tcp": "localhost:26622", "interval": "10s", "timeout": "1s" } }   ttl  check: { "check": { "id": "web-app", "name": "Web APP status", "notes": "Web APP does a curl  internally every 10 seconds", "ttl": "30s" } }   三、更新consul版本为最新版本1.2.3. 版本更新特性: https://github.com/hashicorp/consul/blob/v1.2.3/CHANGELOG.md

ui较之前有很大改变:     from:https://www.cnblogs.com/cuishuai/p/8194345.html