1、SpringCloud简介
Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等操作提供了一种简单的开发方式。
Spring Cloud包含了多个子项目(针对分布式系统中涉及的多个不同开源产品),比如:Spring Cloud Config、Spring Cloud Netflix、Spring Cloud0 CloudFoundry、Spring Cloud AWS、Spring Cloud Security、Spring Cloud Commons、Spring Cloud Zookeeper、Spring Cloud CLI等项目。
2、服务治理
由于Spring Cloud为服务治理做了一层抽象接口,所以在Spring Cloud应用中可以支持多种不同的服务治理框架,比如:Netflix Eureka、Consul、Zookeeper。在Spring Cloud服务治理抽象层的作用下,我们可以无缝地切换服务治理实现,并且不影响任何其他的服务注册、服务发现、服务调用等逻辑。
Spring Cloud Eureka
Spring Cloud Eureka是Spring Cloud Netflix项目下的服务治理模块。而Spring Cloud Netflix项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用提供了自配置的Netflix OSS整合。通过一些简单的注解,开发者就可以快速的在应用中配置一下常用模块并构建庞大的分布式系统。它主要提供的模块包括:服务发现(Eureka),断路器(Hystrix),智能路由(Zuul),客户端负载均衡(Ribbon)等。
创建“服务注册中心”
创建一个maven工程,我们将其命名为microservice-spring-cloud,并在pom.xml文件中引入如下的内容:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.1.RELEASE</version> </parent> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
然后我们在上面工程的基础上,创建一个它的子模块。如果使用IDEA的话,直接在工程名右键,选择New--->Module。子模块我们将其命名为microservice-discovery-eureka。子模块的pom.xml文件中,我们需要引入如下的内容:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> </dependencies>
由于我们没有使用Spring Initializr来创建工程,所以我们需要自己手动写一个SpringBoot的启动类。然后我们通过@EnableEurekaServer这个注解启动一个服务注册中心提供给其他应用进行对话,这一步非常简单,只需要在SpringBoot的启动类上添加这个注解即可。所以,整体代码如下:
@SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
在默认设置下,该服务注册中心也会将自己作为客户端来尝试注册它自己,所以我们需要禁用它的客户端注册行为,只需要在application.yml
配置文件中增加如下信息:
security:
basic:
enabled: true
user:
name: admin
password: admin123
spring:
application:
name: microservice-discovery-eureka
server:
port: 1001
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://admin:admin123@localhost:1001/eureka
为了与后续要进行注册的服务区分,这里将服务注册中心的端口通过server.port属性设置为1001。启动工程后,访问:http://localhost:1001/,输入配置文件中配置的账号和密码,可以看到下面的页面,其中还没有发现任何服务。
创建“服务提供方”
同样在父工程下,新建一个子模块,新的子模块我们命名为microservice-provider-user,创建完成后,我们在pom.xml文件中,引入如下所示的内容:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <!--监控系统健康情况的工具--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>
可以看到我们在pom文件中,引入了JPA模块、web模块、H2数据库,引入这些坐标是为我们的后续的演示做准备。除此之外,还有spring-cloud-starter-eureka这个坐标。
在当前这个新创建的子模块中,我们在resources目录下,创建一个schema.sql文件和data.sql文件,schema.sql文件用于创建一个表,data.sql文件用于给表中插入一些测试数据。
schema.sql
drop table user if exists; create table user( id bigint generated by default as identity , username varchar(40) , name varchar(40) , age int(3), balance decimal (10,2), primary key(id) );
data.sql
insert into user(id,username,name,age,balance) values (1,'user1','张三',18,100.00); insert into user(id,username,name,age,balance) values (2,'user2','李四',19,101.00); insert into user(id,username,name,age,balance) values (3,'user3','王五',20,102.00); insert into user(id,username,name,age,balance) values (4,'user4','周六',21,103.00);
application.yml
server:
port: 2001
spring:
jpa:
generate-ddl: false
show-sql: true
hibernate:
ddl-auto: none
datasource:
platform: h2
schema: classpath:schema.sql
data: classpath:data.sql
application:
name: microservice-provider-user
eureka:
client:
healthcheck:
enabled: true
serviceUrl:
defaultZone: http://admin:admin123@localhost:1001/eureka
instance:
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
通过spring.application.name
属性,我们可以指定微服务的名称后续在调用的时候只需要使用该名称就可以进行服务的访问。eureka.client.serviceUrl.defaultZone
属性对应服务注册中心的配置内容,指定服务注册中心的位置。为了在本机上测试区分服务提供方和服务注册中心,使用server.port
属性设置不同的端口。
接下来,开始编码工作。
User实体类
package cn.zhuangxp.entity; import javax.persistence.*; import java.io.Serializable; import java.math.BigDecimal; @Entity public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column private String username; @Column private String name; @Column private short age; @Column private BigDecimal balance; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getName() { return name; } public void setName(String name) { this.name = name; } public short getAge() { return age; } public void setAge(short age) { this.age = age; } public BigDecimal getBalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } }
UserDao接口
public interface UserDao extends JpaRepository<User,Long> { }
UserController
@RestController public class UserController { @Autowired private UserDao userDao; @GetMapping("/getUser/{id}") public User getUserById(@PathVariable("id") Long id){ User user = userDao.findOne(id); return user; } }
最后使我们的启动类MainAppProvider
@SpringBootApplication @EnableEurekaClient public class MainAppProvider { public static void main(String[] args) { SpringApplication.run(MainAppProvider.class, args); } }
@EnableEurekaClient注解能激活Eureka中的DiscoveryClient实现,这样才能实现Controller中对服务信息的输出。
上述工作完成,我们就可以启动我们的工程了。启动后,可以在注册中心看到我们的工程。
我们继续访问这个模块提供的接口,打开浏览器,输入http://localhost:2001/getUser/1,可以看到浏览器成功为我们响应了数据