引入相关Plugin Starter依赖到pom.xml
必须为微服务定义一个版本号(version),在application.properties或者yaml的metadata里
必须为微服务自定义一个便于为微服务归类的Key,例如组名(group)或者应用名(application),在application.properties或者yaml的metadata里,便于远程配置中心推送和灰度界面分析
使用者只需要关注相关规则推送。可以采用如下方式之一:
通过远程配置中心推送规则
通过控制台界面推送规则
通过客户端工具(例如Postman)推送推测
请访问http://www.iqiyi.com/w_19rzwzovrl.html,视频清晰度改成720P,然后最大化播放。
请访问https://pan.baidu.com/s/1eq_N56VbgSCaTXYQ5aKqiA,获取更清晰的视频 Alt text Alt text。
如果你是运维负责人,是否会经常发现,你掌管的测试环境中的服务注册中心,被一些不负责的开发人员把他本地开发环境注册上来,造成测试人员测试失败。你希望可以把本地开发环境注册给屏蔽掉,不让注册。
如果你是运维负责人,生产环境的某个微服务集群下的某个实例,暂时出了问题,但又不希望它下线。你希望可以把该实例给屏蔽掉,暂时不让它被调用。
如果你是业务负责人,鉴于业务服务的快速迭代性,微服务集群下的实例发布不同的版本。你希望根据版本管理策略进行路由,提供给下游微服务区别调用,达到多版本灰度访问控制。
如果你是测试负责人,希望对微服务做A/B测试,那么通过动态改变版本达到该目的。
具有极大灵活性——支持在任何环节做过滤控制和版本灰度发布。
具有极小限制性——只要开启了服务注册发现,程序入口加了@EnableDiscoveryClient。
基于黑/白名单的IP地址过滤机制禁止对相应的微服务进行注册。
基于最大注册数的限制微服务注册。一旦微服务集群下注册的实例数目已经达到上限,将禁止后续的微服务进行注册。
基于黑/白名单的IP地址过滤机制禁止对相应的微服务被发现。
基于版本配对,通过对消费端和提供端可访问版本对应关系的配置,在服务发现和负载均衡层面,进行多版本访问控制。
通过规则改变,实现灰度发布。
通过版本切换,实现灰度发布。
实现通过XML进行上述规则的定义。
对接远程配置中心,默认集成阿里巴巴的Nacos,异步接受远程配置中心主动推送规则信息,动态改变微服务的规则。
结合Spring Boot Actuator,异步接受Rest主动推送规则信息,动态改变微服务的规则。
结合Spring Boot Actuator,动态改变微服务的版本。
在服务注册层面的控制中,一旦禁止注册的条件触发,主动推送异步事件,以便使用者订阅。
使用者可以自定义更多的规则过滤条件。
使用者可以对服务注册发现核心事件进行监听。
开发环境的本地微服务(例如IP地址为172.16.0.8)不希望被注册到测试环境的服务注册发现中心,那么可以在配置中心维护一个黑/白名单的IP地址过滤(支持全局和局部的过滤)的规则。
我们可以通过提供一份黑/白名单达到该效果。
当某个微服务注册数目已经达到上限(例如10个),那么后面起来的微服务,将再也不能注册上去。
开发环境的本地微服务(例如IP地址为172.16.0.8)已经注册到测试环境的服务注册发现中心,那么可以在配置中心维护一个黑/白名单的IP地址过滤(支持全局和局部的过滤)的规则,该本地微服务不会被其他测试环境的微服务所调用。
我们可以通过推送一份黑/白名单达到该效果。
A服务调用B服务,而B服务有两个实例(B1、B2),虽然三者相同的服务名,但功能上有差异,需求是在某个时刻,A服务只能调用B1,禁止调用B2。在此场景下,我们在application.properties里为B1维护一个版本为1.0,为B2维护一个版本为1.1。
我们可以通过推送A服务调用某个版本的B服务对应关系的配置,达到某种意义上的灰度控制,切换版本的时候,我们只需要再次推送即可。
在A/B测试中,通过动态改变版本,不重启微服务,达到访问版本的路径改变。
假设当前生产环境,调用路径为网关(V1.0)->服务A(V1.0)->服务B(V1.0)。
运维将发布新的生产环境,部署新服务集群,服务A(V1.1),服务B(V1.1)。
由于网关(1.0)并未指向服务A(V1.1),服务B(V1.1),所以它们是不能被调用的。
新增用作灰度发布的网关(V1.1),指向服务A(V1.1)->服务B(V1.1)。
灰度网关(V1.1)发布到服务注册发现中心,但禁止被服务发现,网关外的调用进来无法负载均衡到网关(V1.1)上。
在灰度网关(V1.1)->服务A(V1.1)->服务B(V1.1)这条调用路径做灰度测试。
灰度测试成功后,把网关(V1.0)指向服务A(V1.1)->服务B(V1.1)。
下线服务A(V1.0),服务B(V1.0),灰度成功。
灰度网关(V1.1)可以不用下线,留作下次版本上线再次灰度发布。
Spring Cloud F版,请采用4.x.x版本,具体代码参考master分支。
Spring Cloud C版、D版和E版,请采用3.x.x版本,具体代码参考Edgware分支。
4.x.x版本由于Swagger和Spring Boot 2.x.x版本的Actuator用法有冲突,故暂时不支持Endpoint功能,其他功能和3.x.x版本一致。
Spring Cloud F版,最好采用Consul的1.2.1服务器版本(或者更高),从https://releases.hashicorp.com/consul/1.2.1/获取。
Spring Cloud C版、D版和E版,必须采用Consul的0.9.3服务器版本(或者更低),从https://releases.hashicorp.com/consul/0.9.3/获取。
Spring Cloud F版,必须采用Zookeeper的3.5.x服务器版本(或者更高)。
Spring Cloud C版、D版和E版,最好采用Zookeeper的3.5.0以下服务器版本(或者更低)。
跟Spring Cloud版本保持一致。
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-starter-eureka</artifactId>
<version>${discovery.plugin.version}</version>
</dependency>
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-starter-consul</artifactId>
<version>${discovery.plugin.version}</version>
</dependency>
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-starter-zookeeper</artifactId>
<version>${discovery.plugin.version}</version>
</dependency>
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-config-center-extension-nacos</artifactId>
<version>${discovery.plugin.version}</version>
</dependency>
独立控制台引入,最后一个如需对接Nacos远程配置中心,则引入:
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-console-starter</artifactId>
<version>${discovery.plugin.version}</version>
</dependency>
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-console-extension-nacos</artifactId>
<version>${discovery.plugin.version}</version>
</dependency>
工程
工程名 | 描述 |
---|---|
discovery-plugin-framework | 核心框架 |
discovery-plugin-framework-eureka | 核心框架的Eureka实现 |
discovery-plugin-framework-consul | 核心框架的Consul实现 |
discovery-plugin-framework-zookeeper | 核心框架的Zookeeper实现 |
discovery-plugin-config-center | 配置中心实现 |
discovery-plugin-config-center-extension-nacos | 配置中心的Nacos扩展 |
discovery-plugin-admin-center | 管理中心实现 |
discovery-plugin-starter-eureka | Eureka Starter |
discovery-plugin-starter-consul | Consul Starter |
discovery-plugin-starter-zookeeper | Zookeeper Starter |
discovery-console | 独立控制台,提供给UI |
discovery-console-extension-nacos | 独立控制台的Nacos扩展 |
discovery-console-starter | Console Starter |
discovery-console-desktop | 图形化灰度发布等桌面程序 |
discovery-springcloud-example-console | 独立控制台示例 |
discovery-springcloud-example-eureka | Eureka服务器 |
discovery-springcloud-example | 灰度发布等示例 |
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<!-- 如果不想开启相关功能,只需要把相关节点删除即可,例如不想要黑名单功能,把blacklist节点删除 -->
<register>
<!-- 服务注册的黑/白名单注册过滤,只在服务启动的时候生效。白名单表示只允许指定IP地址前缀注册,黑名单表示不允许指定IP地址前缀注册。每个服务只能同时开启要么白名单,要么黑名单 -->
<!-- filter-type,可选值blacklist/whitelist,表示白名单或者黑名单 -->
<!-- service-name,表示服务名 -->
<!-- filter-value,表示黑/白名单的IP地址列表。IP地址一般用前缀来表示,如果多个用“;”分隔,不允许出现空格 -->
<!-- 表示下面所有服务,不允许10.10和11.11为前缀的IP地址注册(全局过滤) -->
<blacklist filter-value="10.10;11.11">
<!-- 表示下面服务,不允许172.16和10.10和11.11为前缀的IP地址注册 -->
<service service-name="discovery-springcloud-example-a" filter-value="172.16"/>
</blacklist>
<!-- <whitelist filter-value="">
<service service-name="" filter-value=""/>
</whitelist> -->
<!-- 服务注册的数目限制注册过滤,只在服务启动的时候生效。当某个服务的实例注册达到指定数目时候,更多的实例将无法注册 -->
<!-- service-name,表示服务名 -->
<!-- filter-value,表示最大实例注册数 -->
<!-- 表示下面所有服务,最大实例注册数为10000(全局配置) -->
<count filter-value="10000">
<!-- 表示下面服务,最大实例注册数为5000,全局配置值10000将不起作用,以局部配置值为准 -->
<service service-name="discovery-springcloud-example-a" filter-value="5000"/>
</count>
</register>
<discovery>
<!-- 服务发现的黑/白名单发现过滤,使用方式跟“服务注册的黑/白名单过滤”一致 -->
<!-- 表示下面所有服务,不允许10.10和11.11为前缀的IP地址被发现(全局过滤) -->
<blacklist filter-value="10.10;11.11">
<!-- 表示下面服务,不允许172.16和10.10和11.11为前缀的IP地址被发现 -->
<service service-name="discovery-springcloud-example-b" filter-value="172.16"/>
</blacklist>
<!-- 服务发现的多版本灰度访问控制 -->
<!-- service-name,表示服务名 -->
<!-- version-value,表示可供访问的版本,如果多个用“;”分隔,不允许出现空格 -->
<version>
<!-- 表示消费端服务a的1.0,允许访问提供端服务b的1.0和1.1版本 -->
<service consumer-service-name="discovery-springcloud-example-a" provider-service-name="discovery-springcloud-example-b" consumer-version-value="1.0" provider-version-value="1.0;1.1"/>
<!-- 表示消费端服务b的1.0,允许访问提供端服务c的1.0和1.1版本 -->
<service consumer-service-name="discovery-springcloud-example-b" provider-service-name="discovery-springcloud-example-c" consumer-version-value="1.0" provider-version-value="1.0;1.1"/>
<!-- 表示消费端服务b的1.1,允许访问提供端服务c的1.2版本 -->
<service consumer-service-name="discovery-springcloud-example-b" provider-service-name="discovery-springcloud-example-c" consumer-version-value="1.1" provider-version-value="1.2"/>
</version>
</discovery>
</rule>
<service consumer-service-name="a" provider-service-name="b" consumer-version-value="1.0" provider-version-value="1.0,1.1"/>
表示消费端1.0版本,允许访问提供端1.0和1.1版本。
<service consumer-service-name="a" provider-service-name="b" provider-version-value="1.0,1.1"/>
表示消费端任何版本,允许访问提供端1.0和1.1版本。
<service consumer-service-name="a" provider-service-name="b" consumer-version-value="1.0"/>
表示消费端1.0版本,允许访问提供端任何版本。
<service consumer-service-name="a" provider-service-name="b"/>
表示消费端任何版本,允许访问提供端任何版本。
<service consumer-service-name="a" provider-service-name="b" consumer-version-value="" provider-version-value="1.0,1.1"/>
表示消费端任何版本,允许访问提供端1.0和1.1版本。
<service consumer-service-name="a" provider-service-name="b" consumer-version-value="1.0" provider-version-value=""/>
表示消费端1.0版本,允许访问提供端任何版本。
<service consumer-service-name="a" provider-service-name="b" consumer-version-value="" provider-version-value=""/>
表示消费端任何版本,允许访问提供端任何版本。
消费端的application.properties未定义版本号,则该消费端可以访问提供端任何版本。
提供端的application.properties未定义版本号,当消费端在xml里不做任何版本配置,才可以访问该提供端。
规则分为本地规则和动态规则。
本地规则是通过在本地规则(例如:rule.xml)文件定义的,也可以从远程配置中心获取,在微服务启动的时候读取。
动态规则是通过POST方式动态设置,或者由远程配置中心推送设置。
规则初始化的时候,如果接入了远程配置中心,先读取远程规则,如果不存在,再读取本地规则文件。
多规则灰度获取规则的时候,先获取动态规则,如果不存在,再获取本地规则。
版本分为本地版本和动态版本。
本地版本是通过在application.properties里配置的,在微服务启动的时候读取。
动态版本是通过POST方式动态设置。
多版本灰度获取版本值的时候,先获取动态版本,如果不存在,再获取本地版本。
全局过滤,指注册到服务注册发现中心的所有微服务,只有IP地址包含在全局过滤字段的前缀中,都允许注册(对于白名单而言),或者不允许注册(对于黑名单而言)。
局部过滤,指专门针对某个微服务而言,那么真正的过滤条件是全局过滤+局部过滤结合在一起。
全局配置值,只下面配置所有的微服务集群,最多能注册多少个。
局部配置值,指专门针对某个微服务而言,那么该值如存在,全局配置值失效。
# Eureka config
eureka.instance.metadataMap.version=1.0
eureka.instance.metadataMap.group=xxx-service-group
# 奇葩的Consul配置(参考https://springcloud.cc/spring-cloud-consul.html - 元数据和Consul标签)
# Consul config(多个值用“,”分隔,例如version=1.0,value=abc)
spring.cloud.consul.discovery.tags=version=1.0,group=xxx-service-group
# Zookeeper config
spring.cloud.zookeeper.discovery.metadata.version=1.0
spring.cloud.zookeeper.discovery.metadata.group=xxx-service-group
功能开关策略
# Plugin config
# 开启和关闭服务注册层面的控制。一旦关闭,服务注册的黑/白名单过滤功能将失效,最大注册数的限制过滤功能将失效。缺失则默认为true
spring.application.register.control.enabled=true
# 开启和关闭服务发现层面的控制。一旦关闭,服务多版本调用的控制功能将失效,动态屏蔽指定IP地址的服务实例被发现的功能将失效。缺失则默认为true
spring.application.discovery.control.enabled=true
# 开启和关闭通过Rest方式对规则配置的控制和推送。一旦关闭,只能通过远程配置中心来控制和推送。缺失则默认为true
spring.application.config.rest.control.enabled=true
# 本地规则文件的路径,支持两种方式:classpath:rule.xml - 规则文件放在resources目录下,便于打包进jar;file:rule.xml - 规则文件放在工程根目录下,放置在外部便于修改。缺失则默认为不装载本地规则
spring.application.config.path=classpath:rule.xml
# 为微服务归类的Key,一般通过group字段来归类,例如eureka.instance.metadataMap.group=xxx-group或者eureka.instance.metadataMap.application=xxx-application。缺失则默认为group
# spring.application.group.key=group
# spring.application.group.key=application
拉取配置,参考discovery-plugin-config-center-extension-nacos工程。
推送配置,参考discovery-console-extension-nacos工程。
一系列批量功能。
跟Nacos集成,实现配置推送和清除。
AbstractRegisterListener,实现服务注册的扩展和监听,用法参考discovery-springcloud-example下MyRegisterListener。
AbstractDiscoveryListener,实现服务发现的扩展和监听,用法参考discovery-springcloud-example下MyDiscoveryListener。注意,在Consul下,同时会触发service和management两个实例的事件,需要区别判断,如下图。
AbstractLoadBalanceListener,实现负载均衡的扩展和监听,用法参考discovery-springcloud-example下MyLoadBalanceListener。
网关Zuul集群部署了1个
微服务集群部署了3个,分别是A服务集群、B服务集群、C服务集群,分别对应的实例数为2、2、3
网关Zuul的1.0版本只能调用服务A的1.0版本,网关Zuul的1.1版本只能调用服务A的1.1版本。
服务A的1.0版本只能调用服务B的1.0版本,服务A的1.1版本只能调用服务B的1.1版本。
服务B的1.0版本只能调用服务C的1.0和1.1版本,服务B的1.1版本只能调用服务C的1.2版本。
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<discovery>
<version>
<!-- 表示网关z的1.0,允许访问提供端服务a的1.0版本 -->
<service consumer-service-name="discovery-springcloud-example-zuul" provider-service-name="discovery-springcloud-example-a" consumer-version-value="1.0" provider-version-value="1.0"/>
<!-- 表示网关z的1.1,允许访问提供端服务a的1.1版本 -->
<service consumer-service-name="discovery-springcloud-example-zuul" provider-service-name="discovery-springcloud-example-a" consumer-version-value="1.1" provider-version-value="1.1"/>
<!-- 表示消费端服务a的1.0,允许访问提供端服务b的1.0版本 -->
<service consumer-service-name="discovery-springcloud-example-a" provider-service-name="discovery-springcloud-example-b" consumer-version-value="1.0" provider-version-value="1.0"/>
<!-- 表示消费端服务a的1.1,允许访问提供端服务b的1.1版本 -->
<service consumer-service-name="discovery-springcloud-example-a" provider-service-name="discovery-springcloud-example-b" consumer-version-value="1.1" provider-version-value="1.1"/>
<!-- 表示消费端服务b的1.0,允许访问提供端服务c的1.0和1.1版本 -->
<service consumer-service-name="discovery-springcloud-example-b" provider-service-name="discovery-springcloud-example-c" consumer-version-value="1.0" provider-version-value="1.0;1.1"/>
<!-- 表示消费端服务b的1.1,允许访问提供端服务c的1.2版本 -->
<service consumer-service-name="discovery-springcloud-example-b" provider-service-name="discovery-springcloud-example-c" consumer-version-value="1.1" provider-version-value="1.2"/>
</version>
</discovery>
</rule>
上述微服务分别见discovery-springcloud-example字样的8个DiscoveryApplication,分别对应各自的application.properties。这8个应用,对应的版本和端口号如下表:
微服务 | 服务端口 | 管理端口 | 版本 |
---|---|---|---|
A1 | 1100 | 5100 | 1.0 |
A2 | 1101 | 5101 | 1.1 |
B1 | 1200 | 5200 | 1.0 |
B2 | 1201 | 5201 | 1.1 |
C1 | 1300 | 5300 | 1.0 |
C2 | 1301 | 5301 | 1.1 |
C3 | 1302 | 5302 | 1.2 |
Zuul | 1400 | 5400 | 1.0 |
服务端口 | 管理端口 |
---|---|
2222 | 3333 |
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-starter-eureka</artifactId>
<!-- <artifactId>discovery-plugin-starter-consul</artifactId> -->
<!-- <artifactId>discovery-plugin-starter-zookeeper</artifactId> -->
<version>${discovery.plugin.version}</version>
</dependency>
根据上面选择的服务注册发现中心,对控制台下的discovery-springcloud-example-console/pom.xml进行组件切换切换。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<!-- <artifactId>spring-cloud-starter-consul-discovery</artifactId> -->
<!-- <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId> -->
</dependency>
在rule.xml把本地IP地址写入到相应地方。
启动DiscoveryApplicationA1.java。
抛出禁止注册的异常,即本地服务受限于黑名单的IP地址列表,不会注册到服务注册发现中心;白名单操作也是如此,不过逻辑刚好相反。
在rule.xml修改最大注册数为0。
启动DiscoveryApplicationA1.java。
抛出禁止注册的异常,即本地服务受限于最大注册数,不会注册到服务注册发现中心。
在rule.xml把本地IP地址写入到相应地方。
启动DiscoveryApplicationA1.java和DiscoveryApplicationB1.java、DiscoveryApplicationB2.java。
你会发现A服务无法获取B服务的任何实例,即B服务受限于黑名单的IP地址列表,不会被A服务的发现;白名单操作也是如此,不过逻辑刚好相反。
请访问http://www.iqiyi.com/w_19s07thtsh.html,视频清晰度改成720P,然后最大化播放。
请访问https://pan.baidu.com/s/1eq_N56VbgSCaTXYQ5aKqiA,获取更清晰的视频。
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<discovery>
<version>
<service consumer-service-name="discovery-springcloud-example-b" provider-service-name="discovery-springcloud-example-c" consumer-version-value="" provider-version-value="3.0"/>
</version>
</discovery>
</rule>
图 1:
在上面基础上,启动discovery-springcloud-example下DiscoveryApplicationZuul。
因为Zuul是一种特殊的微服务,所有操作过程跟上面完全一致。
文章浏览阅读3.1k次,点赞3次,收藏15次。diff算法的作用计算出Virtual DOM中真正变化的部分,并只针对该部分进行原生DOM操作,而非重新渲染整个页面。传统diff算法通过循环递归对节点进行依次对比,算法复杂度达到 O(n^3) ,n是树的节点数,这个有多可怕呢?——如果要展示1000个节点,得执行上亿次比较。。即便是CPU快能执行30亿条命令,也很难在一秒内计算出差异。React的diff算法(1)什么是调和?将..._安卓面试题 diff算法有哪些
文章浏览阅读2.6k次。在ubutun14 系统中安装vagrant执行vagrant up时会出现:==> default: Booting VM... ==> default: Waiting for machine to boot. This may take a few minutes... default: SSH address: 127.0.0.1:2222 de_cmd中vagrant up超时
文章浏览阅读1w次,点赞8次,收藏40次。注:参考书籍《Python数据结构与算法》1.图的抽象数据类型定义Graph()新建一个空图;addVertex(vert)向图中添加一个顶点(vert)实例;addEdge(fromVert,toVert)向图中添加一条有向边,用于连接顶点fromVert,toVertaddEdge(fromVert,toVert,weight)向图中添加一条带权重(weight)的有向边getVertex(vertKey)在图中找到名为vertKey的顶点getVertices()以列表形_python 图算法
文章浏览阅读1.1w次,点赞5次,收藏80次。销售管理系统 JavaGUI Swing框架实现版_销售管理系统
文章浏览阅读372次。现在有两个集合set1 和 set2, 需要将这两个集合合并成一个集合。 思路很简单: 顺序查找set1中的元素set2是否包含,是,则找下一个,否,加入到set2。 最后返回set2scheme 实现:(define (union_set set1 set2) (if (null? set1) set2 (union_set (cdr set1) (a_set thinker
文章浏览阅读5k次。研究一下贝塞尔曲线./** * 贝塞尔方程 */ private class BeizerEvaluator implements TypeEvaluator { private PointF point1; private PointF point2; private PointF pointF;_android 贝塞尔曲线融合动画
文章浏览阅读1k次。不同类型的DMAGPIOPL general purpose AXIGP AXI utlilizing PS DMACHigh performance w/DMAACP w/DMA几种DMA的总结ZYNQ中不同应用类型的DMA 几个常用的 AXI 接口 IP 的功能(上面已经提到): AXI-DMA:实现从 PS 内存到 PL 高速传输高速通道 AXI-HP<---->AXI-Stream 的转换 AXI-FIFO-MM2S:实现从 PS 内存到._dma cdma
文章浏览阅读938次。声明:本文转载自http://www.chinacion.cn/article/7931.html,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。这一篇文章我们就用 Java 来生成一下仿金山词霸的海报。As long as you can still grab a breath, you fight. 只要一息尚存,就不得不战。有那么一段时..._java生成小程序二维码海报
文章浏览阅读870次。人工神经网络(ArtificialNeuralNetwork,即ANN)是从信息处理角度对人脑神经元网络进行抽象,是20世纪80年代以来人工智能领域兴起的研究热点,其本质是一种运算模型,由大量的节点(或称神经元)之间相互联接构成,在模式识别、智能机器人、自动控制、生物、医学、经济等领域已成功地解决了许多现代计算机难以解决的实际问题,表现出了良好的智能特性。_人工神经元的结构以及各部分功能
文章浏览阅读2.3k次。#windmill{ width:160px; height:160px; position:relative; -moz-transition:-moz-transform 2s ease-in-out; -webkit-transition:-webkit-transform 2s ease-in-out; -moz-transform:rotate(0deg); -webki_h5 css写风车转动
文章浏览阅读3.9k次。如何判断windows动态链接库是32还是64位从 http://www.cnblogs.com/conorpai/p/6393120.html 转载而来如果安装过Visual Studio的话,直接打开一个VS提供的控制台窗口,比如VS2012 x64 Native Tools Command Prompt.用下面的命令查看程序的头部信息:“dumpbin /_win32动态链接库有64位版本吗
文章浏览阅读2k次。原标题:从EMUI的6次里程碑事件,看华为对安卓生态的贡献从华为进入手机领域开始至今,EMUI的发展共经历了5次较大的里程碑事件。由于安卓的开源属性,因此,每一次关键问题的解决和核心难题的攻克都是对安卓生态发展的一次贡献。 EMUI5.0:天生一,一生快用安卓的机友都深有体会,安卓系统最大的顽疾就是用几个月,系统就会变得异常卡顿。针对该问题,华为手机在EMUI5.0的时候,推出了“天生一,一生快”..._华为对安卓的贡献