SpringCloud服务注册中心双节点集群(Eureka集群)

SpringCloud服务注册中心双节点集群(Eureka集群)0、前言    最近在进行重构一个新项目,为了后续更好的落地,适应于日新月异的技术更新,进行了各方的技术选型及技术预研,最终选型基于微服务架构体系进行开发重构。项目构建前最重要的一步就是要想清楚,整体的部署架构、高可用性(HA)等等,做好前期的部署架构技术调研,确定最终方案。    在微服务架构体系中,核心技术便是SpringCloud,通过登录官网查看SpringClo…

大家好,又见面了,我是你们的朋友全栈君。

0、前言

        最近在进行重构一个新项目,为了后续更好的落地,适应于日新月异的技术更新,进行了各方的技术选型及技术预研,最终选型基于微服务架构体系进行开发重构。项目构建前最重要的一步就是要想清楚,整体的部署架构、高可用性(HA)等等,做好前期的部署架构技术调研,确定最终方案。

        在微服务架构体系中,核心技术便是Spring Cloud,通过登录官网查看SpringCloud已经集成了好多优质的项目,供我们使用借鉴。而SpringCloud Eureka是云端服务发现,一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移,并且支持集群部署。因此,本次部署架构技术方案选型打算采用Eureka集群。

(关于Eureka服务注册与发现请查看上一章节内容【SpringCloud系列】一、SpringCloud服务注册与发现(Eureka))

         本文将阐述SpringCloud服务注册中心双节点集群(Eureka集群)方案及集群demo。


1、Eureka集群概述

1.1 基本原理

SpringCloud服务注册中心双节点集群(Eureka集群)

如上图,是Eureka集群配置图。

– 不同节点的Eureka Server通过Replicate(复制)进行数据同步
– Application Service为服务提供者
– Application Client为服务消费者
– Make Remote Call完成一次服务调用

        服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址(即:服务应用名,spring.application.name参数配置),然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。

        当服务注册中心Eureka Server检测到服务提供者因为宕机、网络原因不可用时,则在服务注册中心将服务置为DOWN状态,并把当前服务提供者状态向订阅者发布,订阅过的服务消费者更新本地缓存。

        服务提供者在启动后,周期性(默认30秒)向Eureka Server发送心跳,以证明当前服务是可用状态。Eureka Server在一定的时间(默认90秒)未收到客户端的心跳,则认为服务宕机,注销该实例。

1.2 Eureka自我保护机制

        在默认配置中,Eureka Server在默认90s没有得到客户端的心跳,则注销该实例,但是往往因为微服务跨进程调用,网络通信往往会面临着各种问题,比如微服务状态正常,但是因为网络分区故障时,Eureka Server注销服务实例则会让大部分微服务不可用,这很危险,因为服务明明没有问题。

         为了解决这个问题,Eureka 有自我保护机制,通过在Eureka Server配置如下参数,可启动保护机制。

eureka.server.enable-self-preservation=true

         它的原理是,当Eureka Server节点在短时间内丢失过多的客户端时(可能发送了网络故障),那么这个节点将进入自我保护模式,不再注销任何微服务,当网络故障回复后,该节点会自动退出自我保护模式。

1.3 Eureka高可用集群

        理论上来讲,因为服务消费者本地缓存了服务提供者的地址,即使Eureka Server宕机,也不会影响服务之间的调用,但是一旦新服务上线,已经在缓存在本地的服务提供者不可用了,服务消费者也无法知道,所以保证Eureka Server的高可用还是很有必要的。

        在分布式系统中,任何的地方存在单点,整个体系就不是高可用的,Eureka 也一样,在上面的架构图中Eureka Server不是以单点存在的,而是以集群的方式对外提供服务。


2、Eureka双中心节点集群

本节以具体示例说明Eureka集群及配置。

2.1 创建Eureka Server

(1)新建springCloudEurekaCluster项目作为Eureka Server集群项目:

SpringCloud服务注册中心双节点集群(Eureka集群)

pom.xml如下:

<?xml version="1.0"?>
<project
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
	xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<modelVersion>4.0.0</modelVersion>
	
	<groupId>com.xcbeyond.springcloud</groupId>
	<artifactId>springCloudEurekaCluster</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springCloudEurekaCluster</name>
	<url>http://maven.apache.org</url>
	
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.RELEASE</version>
		<relativePath/>
	</parent>
	
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
			<version>2.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
			<version>2.0.0.RELEASE</version>
		</dependency>
	</dependencies>
	
	<description>Eureka集群</description>
</project>

(2)配置application.properties。

    在Eureka Server集群时,需要部署多个节点,则需要同一个项目,使用不同的配置。因此,在本例中使用springCloudEurekaCluster一个项目通过不同的启动参数来启动占用不同端口的两个Server服务,来模拟Eureka集群。则使用下面三个*.properties配置文件:

  • application.properties
  • application-eureka-server1.properties
  • application-eureka-server2.properties

application.properties

#应用名
spring.application.name=eureka-cluster

application-eureka-server1.properties

##eureka-server1节点配置,配置参数--spring.profiles.active=eureka-server1来启动该环境
spring.profiles=eureka-server1
server.port=8761
eureka.instance.hostname=eureka-server1
eureka.client.serviceUrl.defaultZone=http://eureka-server2:8762/eureka/

application-eureka-server2.properties

##eureka-server2节点配置,配置参数--spring.profiles.active=eureka-server2来启动该环境
spring.profiles=eureka-server2
server.port=8762
eureka.instance.hostname=eureka-server2
eureka.client.serviceUrl.defaultZone=http://eureka-server1:8761/eureka/

       application-eureka-server1.properties、application-eureka-server2.properties配置文件设置了不同的端口(server.port),重点是参数eureka.client.serviceUrl.defaultZone,分别配置对方的地址作为Eureka Client进行相互注册。由于采用了参数配置eureka.instance.hostname及http://eureka-server1的写法,则需要在进行hosts的配置,window在C:\Windows\System32\drivers\etc\hosts,Linux是在/etc/host,此处,以我windows本机说明,在hosts文件中最近如下配置:

127.0.0.1 eureka-server1
127.0.0.1 eureka-server2

(3)新建启动类。

com.xcbeyond.springcloud.eurekacluster.EurekaClusterApplication.java

package com.xcbeyond.springcloud.eurekacluster;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * Eureka集群启动类
 * @author xcbeyond
 * 2018年8月7日上午10:34:01
 */
@SpringBootApplication
//开启对EurekaServer的支持,即:作为Eureka服务端
@EnableEurekaServer
//开启作为Eureka Server的客户端的支持
@EnableDiscoveryClient
public class EurekaClusterApplication {
	public static void main(String[] args) {
		SpringApplication.run(EurekaClusterApplication.class, args);
	}
}

重点添加@EnableEurekaServer注解,开启对EurekaServer的支持,即:作为Eureka服务端。

项目源码:https://download.csdn.net/download/xcbeyond/10592831

2.2.Eureka集群启动及验证

2.2.1 集群启动

      在创建Eureka server项目时,创建了两个properties配置文件,作为集群不同的节点配置文件,在启动项目时,只需指定启动参数–spring.profiles.active=eureka-server1来指定对应配置环境,运行启动类即可。Eclipse IDE开发环境下,配置启动参数方式如下:

SpringCloud服务注册中心双节点集群(Eureka集群)

在启动第一个节点eureka-server1过程中,会持续出现如下错误信息:

2018-08-09 10:29:25.225 ERROR 7964 --- [nfoReplicator-0] c.n.d.s.t.d.RedirectingEurekaHttpClient  : Request execution error

com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect
	at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:187) ~[jersey-apache-client4-1.19.1.jar:1.19.1]
	at com.sun.jersey.api.client.filter.GZIPContentEncodingFilter.handle(GZIPContentEncodingFilter.java:123) ~[jersey-client-1.19.1.jar:1.19.1]
	at com.netflix.discovery.EurekaIdentityHeaderFilter.handle(EurekaIdentityHeaderFilter.java:27) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.sun.jersey.api.client.Client.handle(Client.java:652) ~[jersey-client-1.19.1.jar:1.19.1]
	at com.sun.jersey.api.client.WebResource.handle(WebResource.java:682) ~[jersey-client-1.19.1.jar:1.19.1]
	at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74) ~[jersey-client-1.19.1.jar:1.19.1]
	at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:570) ~[jersey-client-1.19.1.jar:1.19.1]
	at com.netflix.discovery.shared.transport.jersey.AbstractJerseyEurekaHttpClient.register(AbstractJerseyEurekaHttpClient.java:56) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$1.execute(EurekaHttpClientDecorator.java:59) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.MetricsCollectingEurekaHttpClient.execute(MetricsCollectingEurekaHttpClient.java:73) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$1.execute(EurekaHttpClientDecorator.java:59) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient.executeOnNewServer(RedirectingEurekaHttpClient.java:118) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient.execute(RedirectingEurekaHttpClient.java:79) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$1.execute(EurekaHttpClientDecorator.java:59) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:120) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$1.execute(EurekaHttpClientDecorator.java:59) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.DiscoveryClient.register(DiscoveryClient.java:829) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.InstanceInfoReplicator.run(InstanceInfoReplicator.java:121) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.InstanceInfoReplicator$1.run(InstanceInfoReplicator.java:101) [eureka-client-1.9.2.jar:1.9.2]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_121]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_121]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_121]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_121]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]
Caused by: java.net.ConnectException: Connection refused: connect
	at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[na:1.8.0_121]
	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) ~[na:1.8.0_121]
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_121]
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_121]
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_121]
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[na:1.8.0_121]
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_121]
	at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_121]
	at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:121) ~[httpclient-4.5.5.jar:4.5.5]
	at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180) ~[httpclient-4.5.5.jar:4.5.5]
	at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:144) ~[httpclient-4.5.5.jar:4.5.5]
	at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:134) ~[httpclient-4.5.5.jar:4.5.5]
	at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:610) ~[httpclient-4.5.5.jar:4.5.5]
	at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:445) ~[httpclient-4.5.5.jar:4.5.5]
	at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:835) ~[httpclient-4.5.5.jar:4.5.5]
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:118) ~[httpclient-4.5.5.jar:4.5.5]
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) ~[httpclient-4.5.5.jar:4.5.5]
	at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:173) ~[jersey-apache-client4-1.19.1.jar:1.19.1]
	... 30 common frames omitted

2018-08-09 10:29:25.225  WARN 7964 --- [nfoReplicator-0] c.n.d.s.t.d.RetryableEurekaHttpClient    : Request execution failed with message: java.net.ConnectException: Connection refused: connect
2018-08-09 10:29:25.225  WARN 7964 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_EUREKA-CLUSTER/xuchao:eureka-cluster:8761 - registration failed Cannot execute request on any known server

com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
	at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:112) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$1.execute(EurekaHttpClientDecorator.java:59) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.DiscoveryClient.register(DiscoveryClient.java:829) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.InstanceInfoReplicator.run(InstanceInfoReplicator.java:121) [eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.InstanceInfoReplicator$1.run(InstanceInfoReplicator.java:101) [eureka-client-1.9.2.jar:1.9.2]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_121]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_121]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_121]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_121]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]

2018-08-09 10:29:25.225  WARN 7964 --- [nfoReplicator-0] c.n.discovery.InstanceInfoReplicator     : There was a problem with the instance info replicator

com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
	at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:112) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$1.execute(EurekaHttpClientDecorator.java:59) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.DiscoveryClient.register(DiscoveryClient.java:829) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.InstanceInfoReplicator.run(InstanceInfoReplicator.java:121) ~[eureka-client-1.9.2.jar:1.9.2]
	at com.netflix.discovery.InstanceInfoReplicator$1.run(InstanceInfoReplicator.java:101) [eureka-client-1.9.2.jar:1.9.2]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_121]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_121]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_121]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_121]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]

     分析日志可知,是在第一个节点eureka-server1启动后,向eureka-server2注册时连接拒绝(java.net.ConnectException: Connection refused: connect)导致,因为此时eureka-server2节点还未启动,所有出现此类错误信息是正常的,eureka-server2启动后,此类错误日志将不会出现。关于各类集群环境不同节点在顺次启动时都会出现类似错误信息的,大家不必惊慌!

       

        在浏览器中分别访问各自节点的地址、端口,http://eureka-server1:8761/、http://eureka-server2:8762/

SpringCloud服务注册中心双节点集群(Eureka集群)

SpringCloud服务注册中心双节点集群(Eureka集群)

从上面两张图可以看出,DS Replicas、registered-replicas、available-replicas分别有了对方的地址,即:相互Replicate、相互注册,则说明Eureka集群成功。

2.2高可用性验证

如果出现其中一个节点宕机,结果将会如何呢?

停掉eureka-server1服务作为模拟宕机,访问http://eureka-server1:8761/显示无法访问,http://eureka-server2:8762/正常访问,eureka-server2节点信息如下:

SpringCloud服务注册中心双节点集群(Eureka集群)

发生变化之处,如上图标注,eureka-server1宕机后,eureka-server2依旧可以发现eureka-server1,而eureka-server1只是变为unavailable-replicas而已,最终不会影响其他客户端的注册。当eureka-server1启动后,一切自动恢复。

(其他高可用性的验证,感兴趣的可一一验证)

SpringCloud服务注册中心双节点集群(Eureka集群)

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/132079.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • SQL Server 中的逻辑读与物理读

    SQL Server 中的逻辑读与物理读

    2021年11月24日
  • idea设置默认maven路径_idea查看maven路径

    idea设置默认maven路径_idea查看maven路径在idea中每次创建maven都要调整位置是不是很烦~可以通过一下方式设置maven默认配置不仅仅对maven有效,其他默认属性同样管用方法介绍:File->OtherSettings->SettingsforNewProject①②开始设置…

    2022年9月1日
  • Hibernate学习笔记

    Hibernate学习笔记

    2021年11月23日
  • visual studio code使用方法_vscode自定义代码块

    visual studio code使用方法_vscode自定义代码块snippet,也即代码片,指的是能够帮助输入重复代码模式,比如循环或条件语句,的模板。本文即旨于详实地介绍如何在vscode中设置snippet。

    2022年10月2日
  • Linux内核移植_rom内核移植

    Linux内核移植_rom内核移植这两天在友善的tiny210的实验板上移植了linux内核,正好和大家分享,同时也算是做个记录吧!首先介绍一下开发环境吧,这个在做移植的时候还是挺重要的。主机linux:Fedora9 安装在VMware虚拟机上;开发板 :友善的tiny210,256M的FLASH;移植linux:LINUX-3.3.5;交叉编译环境:arm-linux-gcc-4.4.3这个是友善24

    2022年9月24日
  • C语言基础知识入门(大全)「建议收藏」

    C语言基础知识入门(大全)「建议收藏」一.C语言入门C语言一经出现就以其功能丰富、表达能力强、灵活方便、应用面广等特点迅速在全世界普及和推广。C语言不但执行效率高而且可移植性好,可以用来开发应用软件、驱动、操作系统等。C语言也是其它众多高级语言的鼻祖语言,所以说学习C语言是进入编程世界的必修课!更多详细进阶教程等你领取!可以关注公众号“C和C加加”回复“ZXC”即可免费获取!二.C语言的具体结构简单来说,一个C程序就是由若干头文件和函数组成。 #include<stdio.h>就是一条预处理命..

    2022年6月7日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号