1. Service Discovery: Eureka Server(服务发现:eureka服务器)

1.1 依赖

         <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

1.2 How to Run a Eureka Server(怎样启动eureka服务器)

下面是一个小型的eureka服务器:

 @SpringBootApplication
@EnableEurekaServer
public class Application { public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
} }

启动后通过http://localhost:{port}来查看主页。

1.3 High Availability, Zones and Regions(高可用,zones和regions)

eureka服务没有后端存储系统,但是服务实例需要不停发送心跳检测来保持他们的注册信息是最新的,所以这些注册信息是存储在内存中的。

客户端也是使用内存来缓存从服务器获取的服务注册信息的。(这样他们就不用每次请求一个服务时都要经过eureka服务器)。

默认情况下,eureka服务器也是一个eureka客户端,并且需要至少一个service URL来定位其他节点。如果你不提供这个URL也可以工作,但是你的日志会出现很多无用的报错信息(它无法注册自己到集群节点中)。

这个问题可以用下面介绍的单节点模式来解决^_^。

1.4 Standalone Mode(单节点模式)

两个缓存(客户端和服务器)和心跳机制的组合使得单节点的Eureka服务器对故障具有相当的弹性,只要有某种监视器或弹性运行时(如Cloud Foundry)保持它的活力。

在单节点模式下需要关闭服务器的客户端行为(不断的尝试连接其他集群节点),如下(application.yml):

 server:
port: 8761 eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

注意:其中serviceUrl是指向本身的。

1.5 Peer Awareness(节点感知)

Eureka服务器可以使用启动多个实例并且相互注册的方法来达到高可用。实际上这是默认行为,你需要做的就是添加节点的serviceUrl。如下(application.yml):

 ---
spring:
profiles: peer1
eureka:
instance:
hostname: peer1
client:
serviceUrl:
defaultZone: http://peer2/eureka/ ---
spring:
profiles: peer2
eureka:
instance:
hostname: peer2
client:
serviceUrl:
defaultZone: http://peer1/eureka/

在上面的例子中我们可以以不同的host来启动同一个应用。启动时指定参数--spring.profiles.active=peer1或者peer2。通过修改操作系统的hosts文件(windows位置C:\Windows\System32\drivers\etc\hosts,linux位置/etc/hosts)就可以解决hostname问题。这样我们就可以在一台主机上测试eureka服务器的节点感知功能了。

你可以添加多个节点到一个系统中,只要它们至少在一端是彼此相连的。它们在自己内部同步注册信息。如果节点在物理上是分离的(在数据中心内部或多个数据中心之间),那么系统原则上可以在“脑裂”类型的故障中存活。(脑裂其实就是在高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障。两个节点上的HA软件像“裂脑人”一样,争抢“共享资源”、争起“应用服务”,就会发生严重后果——或者共享资源被瓜分、2边“服务”都起不来了;或者2边“服务”都起来了,但同时读写“共享存储”,导致数据损坏)。

1.6 When to Prefer IP Address(何时使用ip地址)

在有些情况下,Eureka推荐使用ip地址而不是hostname。通过设置eureka.instance.preferIpAddress=true。

注意:如果java决定不了hostname那么就会把ip地址发送给eureka。通过eureka.instance.hostname可以显式的设置hostname。或者设置环境变量。

1.7 Securing The Eureka Server(保护eureka服务器)

添加spring-boot-starter-security到你的classpath。默认情况下,当spring security在classpath中时,它要求每个请求都必须含有CSRF token。不过一般Eureka客户端都没有CSRF token,所以需要将路径/eureka/**放开。

如下:

 @EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().ignoringAntMatchers("/eureka/**");
super.configure(http);
}
}

2 Service Discovery: Eureka Clients(服务发现:eureka客户端)

2.1 依赖

         <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2.2 Registering with Eureka(通过eureka注册)

当一个客户端注册到Eureka时,它会提供自身的一些元数据(主机,端口,健康状态指示器url,主页,和其他一些细节)。Eureka会接受到来自服务实例的心跳信息。如果心跳在一段时间没有接收到,则Eureka将会移除对应的实例。

下面是一个简单的eureka客户端:

 @SpringBootApplication
@RestController
public class Application { @RequestMapping("/")
public String home() {
return "Hello world";
} public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
} }

application.yml:

 eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/

在classpath上存在spring-cloud-starter-netflix-eureka-client会是你的app变成eureka“实例”(将自身注册到eureka)和eureka“客户端”(从eureka获取其他服务的信息)。其中实例的行为可以使用eureka.instance.*来设置。

一般来说默认值就够用了,你只需要设置一下spring.application.name,因为它是eureka默认的service ID。

如果你只对外提供服务而不需要从eureka获取其他服务信息,那么你可以关闭对应的“客户端”行为。使用eureka.client.enabled=false。

2.3 Authenticating with the Eureka Server(使用eureka服务器进行身份验证)

如果eureka.client.serviceUrl.defaultZone的URL中含有用户凭证信息(http://user:password@localhost:8761/eureka),HTTP基本验证将会自动添加到eureka客户端中。但是如果有更复杂的需求的话,需要定义一个

DiscoveryClientOptionalArgs类型的bean,并且在其中注入一个ClientFilter实例,它会应用到客户端到服务端的所有请求上。

2.4 Using the EurekaClient(使用EurekaClient)

只要你的app是一个eureka客户端,你就可以从eureka服务器获取其他服务的信息。其中一种方法就是使用原生的com.netflix.discovery.EurekaClient,如下:

 @Autowired
private EurekaClient discoveryClient; public String serviceUrl() {
InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES", false);
return instance.getHomePageUrl();
}

注意:别在@PostConstruct或者@Scheduled方法里使用EurekaClient,或者任何其他ApplicationContext还没启动的地方。

2.5 Alternatives to the Native Netflix EurekaClient(原生Netflix EurekaClient的替代方法)

可以使用org.springframework.cloud.client.discovery.DiscoveryClient,提供了一些简单的API来获取其他注册服务信息。例如:

 @Autowired
private DiscoveryClient discoveryClient; public String serviceUrl() {
List<ServiceInstance> list = discoveryClient.getInstances("STORES");
if (list != null && list.size() > 0 ) {
return list.get(0).getUri();
}
return null;
}

2.6 Why Is It so Slow to Register a Service?(为啥注册一个服务这么慢?)

注册成为一个实例需要发送周期性的心跳到注册中心,默认值为30秒。直到实例,服务器,客户端在他们本地的缓存中有同样的元数据(可能需要3次心跳)一个服务才能被其他客户端发现。

可以通过设置eureka.instance.leaseRenewalIntervalInSeconds来改变周期。把它设置成一个小于30的值会使客户端更快的连接到其他服务上。但是在生产环境中最好使用默认值,因为服务器内部的计算假设了租赁续期。

2.7 Zones

如果你把客户端部署到不同的区域,你可以通过设置来使客户端优先使用同一区域中的服务。

第一步,确保你的eureka服务器部署到了各个区域,并且是彼此的节点。

第二步,你需要告诉eureka服务器你的服务处于哪个区域,使用metadataMap来设置。下面的例子中service 1被部署到了zone1和zone2.

Service 1 in Zone 1:

 eureka.instance.metadataMap.zone = zone1
eureka.client.preferSameZoneEureka = true

Service 1 in Zone 2:

eureka.instance.metadataMap.zone = zone2
eureka.client.preferSameZoneEureka = true

3. Circuit Breaker: Hystrix Clients(断路器:Hystrix客户端)

3.1 依赖

         <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

下面是一个简单的含有Hystrix断路器的eureka服务器:

 @SpringBootApplication
@EnableCircuitBreaker
public class Application { public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
} } @Component
public class StoreIntegration { @HystrixCommand(fallbackMethod = "defaultStores")
public Object getStores(Map<String, Object> parameters) {
//do stuff that might fail
} public Object defaultStores(Map<String, Object> parameters) {
return /* something useful */;
}
}

3.2 Propagating the Security Context or Using Spring Scopes(传播安全上下文或者使用spring scopes)

如果你想传递线程本地上下文到@HystrixCommand中,默认配置是不行的,因为它是在线程池中执行命令的。你可以通过配置文件或者直接在注解中配置来使Hystrix使用调用者的线程。即使用一个不同的“Isolation Strategy”。

下面的例子展示了如果在注解中设置线程:

 @HystrixCommand(fallbackMethod = "stubMyService",
commandProperties = {
@HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")
}
)
...

你也可以选择使用hystrix.shareSecurityContext=true。这么做将会自动配置一个Hystrix并发性策略插件钩子来将SecurityContext从主线程中传递到Hystrix线程中。Hystrix不允许多个并发性策略被注册,所以你可以配一个你自己的

HystrixConcurrencyStrategy bean。Spring Cloud会在spring上下文中查找你的实现并且将它包装到它自己的插件中去。

4. Hystrix Timeouts And Ribbon Clients(Hystrix超时和Ribbon客户端)

当使用包含Ribbon客户端的Hystrix命令时,你要保证Hystrix的超时时间比Ribbon的超时时间长,包含潜在的重试机制。举个例子:Ribbon的超时时间是1秒,而且会在超时时重试3次,那么你的Hystrix的超时时间应该设置大于3秒。

4.1 Hystrix Dashboard依赖

         <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

在spring boot的启动类上添加@EnableHystrixDashboard注解。然后访问/hystrix,并且指向一个Hystrix客户端的/hystrix.stream端点。

4.2 Turbine

查看一个单独实例的Hystrix的数据对于整个系统整体而言通常意义不大。Turbine可以将所有相关的/hystrix.stream关联到/turbine.stream来供Hystrix Dashboard使用。每个单独的应用实例可以使用eureka来定位。

启动Turbine需要在启动类上添加注解@EnableTurbine,不同的是turbine.instanceUrlSuffix不需要提供端口,因为它会自动添加,除非设置了turbine.instanceInsertPort=false。

注意:默认情况下,Turbine查找/hystrix.stream是通过注册实例在eureka中的hostName和port信息并且在后面添加/hystrix.stream。如果注册实例的元数据中存在management.port属性的话,那么/hystrix.stream端点将会使用

它代替之前的port。默认,元数据中的management.port和配置属性的management.port是相同的。可以通过下面的设置来覆盖:

 eureka:
instance:
metadata-map:
management.port: ${management.port:8081}

turbine.appConfig配置是一个eureka serviceId的列表,Turbine用它来查找实例。Turbine stream在Hystrix Dashboard中使用的url如下:

 http://my.turbine.server:8080/turbine.stream?cluster=CLUSTERNAME

其中cluster参数可以省略,如果名称是默认的话。cluster参数必须匹配turbine.aggregator.clusterConfig。从Eureka返回的值都是大写的。

 turbine:
aggregator:
clusterConfig: CUSTOMERS
appConfig: customers

你可以通过定义一个TurbineClustersProvider的bean来定制化cluster名称。

cluster name还可以使用SPEL在turbine.clusterNameExpression配置。cluster name默认就是实例在eureka注册的serviceId。下面使用一个不一样的例子:

 turbine:
aggregator:
clusterConfig: SYSTEM,USER
appConfig: customers,stores,ui,admin
clusterNameExpression: metadata['cluster']

在上面的例子中,四个服务的cluster name是从他们在注册中心实例信息的metadata map中获取的。

如果将所有服务都归纳到一个cluster name下,则可以使用“default”,如下(注意单引号和双引号):

 turbine:
appConfig: customers,stores
clusterNameExpression: "'default'"

4.2.1 Clusters Endpoint(Clusters端点)

通过/clusters路径可以查看当前Turbine存在哪些clusters:

 [
{
"name": "RACES",
"link": "http://localhost:8383/turbine.stream?cluster=RACES"
},
{
"name": "WEB",
"link": "http://localhost:8383/turbine.stream?cluster=WEB"
}
]

如果要禁用这个端点可以使用turbine.endpoints.clusters.enabled=false。

5. Client Side Load Balancer: Ribbon(客户端负载均衡器:Ribbon)

Ribbon是一个端客户端的负载均衡器,它给了HTTP或者TCP客户端行为的很多控制。Feign用的就是Ribbon。如果你使用了Feign那么本节也值得一看。

5.1 How to Include Ribbon(依赖)

         <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

5.2 Customizing the Ribbon Client(自定义Ribbon客户端)

可以通过外部配置<client>.ribbon.*来配置一些Ribbon客户端属性。Spring Cloud也允许你使用@RibbonClient来申明额外的配置来完全掌控Ribbon客户端。如下:

 @Configuration
@RibbonClient(name = "custom", configuration = CustomConfiguration.class)
public class TestConfiguration {
}

在上面这个例子中,客户端是由RibbonClientConfiguration中的组件和CustomConfiguration中的所有组件组成(后者会覆盖前者)。

注意:CustomConfiguration必须是一个@Configuration类,并且要保证它不在@ComponentScan扫描范围内。否则它就会被所有Ribbon客户端共享。

下表是Spring Cloud Netflix为Ribbon提供的默认值:

Bean Type Bean Name Class Name
IClientConfig ribbonClientConfig DefaultClientConfigImpl
IRule ribbonRule ZoneAvoidanceRule
IPing ribbonPing DummyPing
ServerList<Server> ribbonServerList ConfigurationBasedServerList
ServerListFilter<Server> ribbonServerListFilter ZonePreferenceServerListFilter
ILoadBalancer ribbonLoadBalancer ZoneAwareLoadBalancer
ServerListUpdater ribbonServerListUpdater PollingServerListUpdater

创建上面类型的bean并且将它放在@RibbonClient配置中可以覆盖默认的配置。如下:

 @Configuration
protected static class FooConfiguration {
@Bean
public ZonePreferenceServerListFilter serverListFilter() {
ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
filter.setZone("myTestZone");
return filter;
} @Bean
public IPing ribbonPing() {
return new PingUrl();
}
}

5.3 Customizing the Default for All Ribbon Clients(为所有Ribbon客户端自定义默认配置)

使用@RibbonClients注解并且注册一个默认配置。如下:

 @RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)
public class RibbonClientDefaultConfigurationTestsConfig { public static class BazServiceList extends ConfigurationBasedServerList {
public BazServiceList(IClientConfig config) {
super.initWithNiwsConfig(config);
}
}
} @Configuration
class DefaultRibbonConfig { @Bean
public IRule ribbonRule() {
return new BestAvailableRule();
} @Bean
public IPing ribbonPing() {
return new PingUrl();
} @Bean
public ServerList<Server> ribbonServerList(IClientConfig config) {
return new RibbonClientDefaultConfigurationTestsConfig.BazServiceList(config);
} @Bean
public ServerListSubsetFilter serverListFilter() {
ServerListSubsetFilter filter = new ServerListSubsetFilter();
return filter;
} }

5.4 Customizing the Ribbon Client by Setting Properties(使用配置文件自定义Ribbon客户端)

从版本1.2.0后Spring Cloud Netflix允许通过属性设置来自定义Ribbon客户端。下面是支持的属性设置:

 <clientName>.ribbon.NFLoadBalancerClassName: Should implement ILoadBalancer
<clientName>.ribbon.NFLoadBalancerRuleClassName: Should implement IRule
<clientName>.ribbon.NFLoadBalancerPingClassName: Should implement IPing
<clientName>.ribbon.NIWSServerListClassName: Should implement ServerList
<clientName>.ribbon.NIWSServerListFilterClassName: Should implement ServerListFilter

注意:在上面这些属性中定义的类比@RibbonClient(configuration=MyRibbonConfig.class和Spring Cloud Netflix提供的默认值具有更高的优先级。

例如(application.yml):

 users:
ribbon:
NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule

5.5 Using Ribbon with Eureka(在Eureka中使用Ribbon)

当Eureka和Ribbon一起使用时,ribbonServerList会被DiscoveryEnabledNIWSServerList的扩展覆盖,NIWSDiscoveryPing覆盖IPing接口授权Eureka来决定服务是否可用。ServerList默认是DomainExtractingServerList。

它的目的是在不使用AWS AMI 元数据的情况下,使负载均衡器可以使用元数据。默认情况下,服务列表是由“zone” 信息组成的(eureka.instance.metadataMap.zone)。如果“zone”不存在并且approximateZoneFromHostname

被设置了,那么将会使用服务主机的域名作为zone的代理。只要当zone信息存在时,就可以在ServerListFilter使用它。

注意:设置客户端区域的传统“archaius”方法是通过一个名为“@zone”的配置属性。如果它是可用的,Spring Cloud优先使用它而不是所有其他设置(注意,键必须在YAML配置中引用)。

5.6 Example: How to Use Ribbon Without Eureka(在没有eureka的情况下使用ribbon)

Eureka是一个抽象远程服务发现的简便方法,这样你就不用在客户端中硬编码他们的URL了。但是如果你不使用Eureka, Ribbon 和 Feign也是可以的。

假设你为"stores"声明了一个@RibbonClient配置类,并且没有使用Eureka。你可以使用如下配置(application.yml):

 stores:
ribbon:
listOfServers: example.com,google.com

5.7 Example: Disable Eureka Use in Ribbon(在Ribbon中禁用Eureka)

显示禁用Eureka(application.yml):

 ribbon:
eureka:
enabled: false

5.8 Using the Ribbon API Directly(直接使用Ribbon API)

public class MyClass {
@Autowired
private LoadBalancerClient loadBalancer; public void doStuff() {
ServiceInstance instance = loadBalancer.choose("stores");
URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
// ... do something with the URI
}
}

5.9 Caching of Ribbon Configuration(Ribbon配置缓存)

每个Ribbon客户端都对应有一个spring cloud的子上下文,这个应用上下文是在第一次请求到Ribbon客户端时才加载的。这种懒加载行为可以通过下面的例子来改变成在启动时加载(application.yml):

ribbon:
eager-load:
enabled: true
clients: client1, client2, client3

5.10 How to Configure Hystrix Thread Pools(如何配置Hystrix线程池)

如果将zuul.ribbonIsolationStrategy设置为THREAD,Hystrix的线程隔离策略将应用于所有路由。在这种情况下,HystrixThreadPoolKey默认被设置为RibbonCommand。这意味着,所有路由的HystrixCommands会在

同一个Hystrix线程池中执行。可以通过如下配置来改变这种行为(application.yml):

 zuul:
threadPool:
useSeparateThreadPools: true

上面的例子将会使每个路由的HystrixCommands在不同的线程池中执行。

这种情况下,默认HystrixThreadPoolKey和每个路由的service ID是一样的。设置zuul.threadPool.threadPoolKeyPrefix可以为HystrixThreadPoolKey添加一个前缀。如下(application.yml):

 zuul:
threadPool:
useSeparateThreadPools: true
threadPoolKeyPrefix: zuulgw

5.11 How to Provide a Key to Ribbon’s IRule(如何给Ribbon IRule提供一个键)

如果你想要实现自定义的IRule来处理一些特别的路由,传递一些信息到IRule的choose方法。

com.netflix.loadbalancer.IRule.java

 public interface IRule{
public Server choose(Object key);
:

可以提供一些信息给IRule的实现来选择一台目标服务器。如下:

 RequestContext.getCurrentContext()
.set(FilterConstants.LOAD_BALANCER_KEY, "canary-test");

如果你向RequestContext中设置键为FilterConstants.LOAD_BALANCER_KEY的值,那么它会传递给IRule的choose方法。上面例子中的代码必须在RibbonRoutingFilter之前执行。Zuul的pre filter是最好的地方。

在pre filte中你可以通过RequestContext获取HTTP头部信息和查询参数信息,因此它可以来决定传递给Ribbon的LOAD_BALANCER_KEY值。如果你没有在RequestContext中设置LOAD_BALANCER_KEY的值,那么

null将会传递给choose方法。

关于Spring Cloud Netflix还剩下一个路由网关zuul,我将会在下一篇博客中给大家讲解。如果看了我的文章后觉得有点帮助的,希望大家多给点点推荐。谢谢大家!写博客也很耗时间的。谢谢大家的支持!

spring cloud连载第三篇之Spring Cloud Netflix的更多相关文章

  1. spring cloud连载第三篇补充之Zuul

    由于Zuul的内容较多所以单独列出一篇来讲.全是干货,如果学到东西的,动动小手给点个推荐^_^  谢谢! 1. Router and Filter: Zuul(路由和过滤:Zuul) 路由是微服务架构 ...

  2. [Spring Cloud实战 | 第六篇:Spring Cloud Gateway+Spring Security OAuth2+JWT实现微服务统一认证授权

    一. 前言 本篇实战案例基于 youlai-mall 项目.项目使用的是当前主流和最新版本的技术和解决方案,自己不会太多华丽的言辞去描述,只希望能勾起大家对编程的一点喜欢.所以有兴趣的朋友可以进入 g ...

  3. Spring Cloud实战 | 最八篇:Spring Cloud +Spring Security OAuth2+ Axios前后端分离模式下无感刷新实现JWT续期

    一. 前言 记得上一篇Spring Cloud的文章关于如何使JWT失效进行了理论结合代码实践的说明,想当然的以为那篇会是基于Spring Cloud统一认证架构系列的最终篇.但关于JWT另外还有一个 ...

  4. Spring Cloud实战 | 第十篇 :Spring Cloud + Seata 1.4.1 + Nacos1.4.0 整合实现微服务架构中逃不掉的话题分布式事务

    Seata分布式事务在线体验地址:https://www.youlai.store 本篇完整源码地址:https://github.com/hxrui/youlai-mall 有想加入开源项目开发的童 ...

  5. Spring Cloud实战 | 第十一篇:Spring Cloud Gateway 网关实现对RESTful接口权限控制和按钮权限控制

    一. 前言 hi,大家好,这应该是农历年前的关于开源项目 的最后一篇文章了. 有来商城 是基于 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT实现的统 ...

  6. 【Spring Cloud & Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权

    一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证授权.鉴权的逻辑,结合 ...

  7. Spring Boot 2.X(三):使用 Spring MVC + MyBatis + Thymeleaf 开发 web 应用

    前言 Spring MVC 是构建在 Servlet API 上的原生框架,并从一开始就包含在 Spring 框架中.本文主要通过简述 Spring MVC 的架构及分析,并用 Spring Boot ...

  8. Spring源码解析 | 第二篇:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析

    一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...

  9. 【面试 spring】【第七篇】spring的问题

    1.spring你熟悉么?两大特色 spring 主要有IOC和AOP两大特色. =========================================================== ...

随机推荐

  1. [LeetCode 题解]:Palindrome Number

    前言   [LeetCode 题解]系列传送门:  http://www.cnblogs.com/double-win/category/573499.html   1.题目描述 Determine ...

  2. Mono For Android 之 配置环境

    下载 Xamarin Mono For Android 4.6.07004 完整离线破解版 (包括除 Android SDK 外的所有文件) Android SDK. 资源源自 http://www. ...

  3. [ucgui] 仪表盘函数

    /* 仪表盘 */ void DrawArcScale(void) { ; ; int i; ]; GUI_SetBkColor(GUI_WHITE); GUI_Clear(); GUI_SetPen ...

  4. MSSQL 全库搜索 指定字符串

    平时在在MSSql中查询数据的时候,想查找,某个字段在数据库中是否存在,并且查询出在哪个表中,哪个字段下面,在不知道的情况下,操作起来会很麻烦,然后就写了一个sql语句,使用起来感觉挺方便的.当然了, ...

  5. 用.netcore写一个简单redis驱动,调试windows版本的redis.平且给set和get命令添加参数.

    1. 下载windows版本的redis 2.开发环境vs2017  新建一个 .net core控制台. private static Socket socket = new Socket(Addr ...

  6. day 59 pymysql

    PyMySQL介绍 PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb. PYmysql安装 pip install pymys ...

  7. OpenvSwitch 解读

    OpenvSwitch 解读 报文匹配流程参考下图 调用流程(内核): ovs_vport_receive->ovs_dp_process_received_packet->ovs_flo ...

  8. 914. X of a Kind in a Deck of Cards

    In a deck of cards, each card has an integer written on it. Return true if and only if you can choos ...

  9. Process Explore & Windbg

    遇到点内存泄漏.句柄泄漏,应该是家常便饭了.这次就是,程序运行内存一点点增加,句柄也是只增不减,个数竟然可以达到几十万,真是瞪大了我的双眼. 借此机会,学习下相关工具~ Process Explore ...

  10. 如何将Excel导入到Mysql数据库中

    1.在mysql中建一张和Excel结构一样的表,或者修改excel信息,将excel的结构与mysql中table保持一致,包括字段名称. 2.利用mysql客户端工具navicat进行导入. 步骤 ...