为什么需要springcloud
1在中大型项目面前,单体应用的缺点就暴露了:
①编译难,部署难,测试难
②技术选择难
③扩展难
这时候就需要微服务了,这种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被技术选型,独立开发,独立部署,独立运维,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。
我们选择Http客户端工具因为
- 速度来看,RPC要比http更快,虽然底层都是TCP,但是http协议的信息往往比较臃肿,不过可以采用gzip压缩。
- 难度来看,RPC实现较为复杂,http相对比较简单
- 灵活性来看,http更胜一筹,因为它不关心实现细节,跨平台、跨语言
接下来就是测试了
idea中maven多模块的方法搭建
搭建父模块 springcloud-parent
<groupId>org.yyf</groupId>
<artifactId>springcloud-parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>eureka-server-7001</module>
<module>eureka-service-8001</module>
<module>product-common</module>
<module>eureka-server-7002</module>
<module>product-consumer-9001</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.SR1</spring-cloud.version>
<springboot.version>2.0.5.RELEASE</springboot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
建立子模块中的公共模块 product-common
java代码
public class Product {
private Long id;
private String name;
搭建服务提供者 eureka-service-8001
<parent>
<artifactId>springcloud-parent</artifactId>
<groupId>org.yyf</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-service-8001</artifactId>
<dependencies>
<!--springboot支持-->
<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>
<!--eureka客户端支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.yyf</groupId>
<artifactId>product-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
application.yml配置
server:
port: 8001
spring:
application:
name: PRODUCT-SERVICE
写服务代码
@RestController
@RequestMapping("/product8")
public class ProductController {
@GetMapping("/{id}")
public Product getProductById(@PathVariable(name="id")Long id){
return new Product(id,"name");
}
}
搭建服务消费者 product-consumer-9001
<parent>
<artifactId>springcloud-parent</artifactId>
<groupId>org.yyf</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>product-consumer-9001</artifactId>
<dependencies>
<!--springboot支持-->
<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>
<!-- Eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.yyf</groupId>
<artifactId>product-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
application.yml配置
server:
port: 9001
spring:
application:
name: PRODUCT-CONSUMER
写消费者调用接口
@Configuration // <beans></beans>
public class CfgBean {
@Bean //<bean class="org.springframework.web.client.RestTemplate"></bean>
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
@RestController
@RequestMapping("/consumer")
public class UserController {
//多个方法调用只需改一处就ok
public static final String URL_PREFIX = "http://localhost:8001";
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/user/{id}")
public User getUser(@PathVariable("id")Long id){
//调用远程服务 http请求
String url = URL_PREFIX+"/provider/user/"+id;
return restTemplate.getForObject(url,User.class );
}
}
无论服务提供者还是消费者都需要入口类
@SpringBootApplication
@EnableEurekaClient
public class ProductService8001Application {
public static void main(String[] args) {
SpringApplication.run(ProductService8001Application.class/ProductService8001Application.class, args);
}
}
正常来说可以通过:http://localhost:9001/consumer/product8/1 来进行测试了
Eureka Server
作为服务注册功能的服务器,它是服务注册时中心。
而系统中的其他微服务,使用eureka的客户端连接到eureka server并维持心跳连接。
Eureka注册中心搭建
创建 eureka_server_7001 模块
<parent>
<artifactId>springcloud-parent</artifactId>
<groupId>org.yyf</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server-7001</artifactId>
<dependencies>
<!--springboot支持-->
<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>
<!--Eureka服务端支持-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
application.yml配置
server:
port: 7001
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false #是否要注册到eureka
fetchRegistry: false #表示是否从Eureka Server获取注册信息
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机配置
入口类
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer7001Application {
public static void main(String[] args) {
SpringApplication.run(EurekaServer7001Application.class, args);
}
}
然后就可以启动EnrekaServerApplication_7001,并进行访问
这时候服务提供者注册到Eureka
pom引入
<!--eureka客户端支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
修改application.yml配置
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka #告诉服务提供者要把服务注册到哪儿
服务消费者也需要从EUreka调用服务
pom’引入
<!-- Eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
application.yml添加
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
添加java代码
@Configuration
public class ConfigBean {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
修改controller
@RestController
@RequestMapping("/product9")
public class ProductController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/product/{id}")
public Product getProductById(@PathVariable("id")Long id){
List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
ServiceInstance serviceInstance = instances.get(0);
String BaseUrl = "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/product8/";
String Url = BaseUrl+id;
return restTemplate.getForObject(Url, Product.class);
}
}
这时候还学要eureka集群,只需要将eurekaserver再拷贝一份,换一个端口
比如eureka-server-7002
pom
<parent>
<artifactId>springcloud-parent</artifactId>
<groupId>org.yyf</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server-7002</artifactId>
<dependencies>
<!--springboot支持-->
<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>
<!--Eureka服务端支持-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
application.yml
server:
port: 7002
eureka:
instance:
hostname: eureka-7002.com #集群
client:
register-with-eureka: false #是否要注册到eureka
fetch-registry: false # 表示是否要从Eureka server 获取注册消息
service-url:
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机配置
defaultZone: http://eureka-7001.com:7001/eureka/ #集群配置,配置除了自己以外,多个用逗号分隔
在7001中application需要修改
service-url:
#defaultZone: http://
e
u
r
e
k
a
.
i
n
s
t
a
n
c
e
.
h
o
s
t
n
a
m
e
:
{eureka.instance.hostname}:
eureka.instance.hostname:{server.port}/eureka/ #单机配置
defaultZone: http://eureka-7002.com:7002/eureka/ #集群配置,配置除了自己以外,多个用逗号分隔
在服务消费者和提供者都修改
service-url:
#defaultZone: http://localhost:7001/eureka #告诉服务提供者要把服务注册到哪儿
#集群配置,每一个注册中心都要配置
defaultZone: http://eureka-7001.com:7001/eureka,http://eureka-7002.com:7002/eureka
然后就大功告成了