赞
踩
首先我们需要先创建以下模块
common-pojo:存放项目的pojo类。
common-dao:存放与数据库相关的持久层代码和配置文件,比如mybatis的mapper接口和文件。
eureka-server:用来启动注册中心,具体请看 注册中心。
customer-provider:用来提供服务,注册服务。
customer-consumer:用来调用服务,处理业务。
上面pojo和mapper具体操作代码就不写了,就是简单的增删改查,可以通过mybatis逆向工程生成代码。
在 common-dao 中依赖mybatis的起步依赖,pom文件如下所示:
<dependencies> <!-- pojo层依赖 --> <dependency> <groupId>com.lbb</groupId> <artifactId>common-pojo</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency> <!-- mybatis的起步依赖 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency> <!-- MySQL连接驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- mybatis分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.11</version> </dependency> </dependencies>
customer-provider,作为服务端工程 服务端需要发布服务,并且将服务注册到Eureka,所以服务端需要添加Eureka的客户端依赖:
<dependencies> <!-- spring web 起步依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.lbb</groupId> <artifactId>common-dao</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency> <!-- eureka起步依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies>
编写Controller。
这部分内容没有任何特殊 的地方,按照之前的写法正常编写即可。我 们可以实现一个根据客户id查询客户信息的方法:
@RestController
public class MyController {
@Autowired
private CrmCustomerMapper customerMapper;
@RequestMapping("custInfo/{id}")
//CrmResult是封装类,封装类一些数据以及状态码,信息
public CrmResult getCustomer(@PathVariable Integer id){
return CrmResult.ok(customerMapper.selectByPrimaryKey(id.longValue()));
}
}
配置文件application.yml
#spring.application.name 在配置文件中我们配置了应用程序的名称,这个名称很重 要,不能重复。将来调用服务时是使用此名称来调用服务的。 spring: application: name: customer-service #数据库信息 datasource: username: root password: 123456 url: jdbc:mysql:///crm?characterEncoding=utf8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver #设置编码问题 http: encoding: force: true charset: UTF-8 #eureka eureka: client: # eureka.client.service-url.defaultZone 属性配置了注册中心的位置 service-url: defaultZone: http://localhost:8000/eureka #下面两个 默认就是true,可以不写 # register-with-eureka: true # fetch-registry: true #端口号 server: port: 9000
启动项
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
//注册到Eureka
@EnableEurekaClient
@MapperScan(basePackages = "com.lbb.crm.dao")
public class ProviderRunner {
public static void main(String[] args) {
SpringApplication.run(ProviderRunner.class,args);
}
}
先启动eureka,再启动服务提供方就可以注册服务成功。
依赖pom
customer-consumer,模块作为消费端工程 消费端也需要连接到Eureka来查询服务信息,所以也需要添加Eureka的客户端依赖,并且消费端 需要调用服务端的服务,所以还需要添加feign的依赖:
<dependencies> <!-- spring web 起步依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.lbb</groupId> <artifactId>common-dao</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency> <!-- eureka起步依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- Feign起步依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies>
配置文件
#spring.application.name 在配置文件中我们配置了应用程序的名称,这个名称很重 要,不能重复。将来调用服务时是使用此名称来调用服务的。 spring: application: name: customer-service #设置编码问题 http: encoding: force: true charset: UTF-8 #eureka eureka: client: # eureka.client.service-url.defaultZone 属性配置了注册中心的位置 service-url: defaultZone: http://localhost:8000/eureka #指定启动端口 server: port: 8787
引导类
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableFeignClients //启用feign进行远程调用
@EnableDiscoveryClient //启用服务注册与发现
public class ConsummerRunner {
public static void main(String[] args) {
SpringApplication.run(ConsummerRunner.class,args);
}
}
在引导类中需要增加 @EnableDiscoveryClient
注解,需要启动服务注册与发现功能。发 现服务后还需要使用Feign来调用工程,所以需要增加 @EnableFeignClients
注解。
创建Feign代理对象
Feign是一个声明式Web Service客户端。使用Feign能让编写Web Service客户端更加简单, 它的使 用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔 插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。
@FeignClient(name = "CUSTOMER-SERVICE")
public interface MyService {
//接口要与服务提供方一致
@RequestMapping("custInfo/{id}")
CrmResult getCrm(@PathVariable Integer id);
}
注意:
@FeignClient 代表我们要创建一个服务端的代理对象,其中 name
属性代表服务端spring.application.name
属性,并且不能包含下划线。
接口中只需要对应服务端发布的服务定义方法即可。
需要注意的是 @PathVariable
注解中必须指定参数名称。否则会报错
调用服务
@RestController
public class MyConSumer {
//在controller中需要调用Feign代理对象的方法来调用服务,只需要将对象注入即可。
@Autowired
private MyService service;
@RequestMapping("get/{id}")
public CrmResult getCrm(@PathVariable Integer id){
return service.getCrm(id);
}
}
此时先启动服务注册中心,在启动服务方,最后启动消费方即可。
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通 过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服 务调用。在Feign中已经集成了Ribbon,我们同时开启多个服务端,会自动实现负载均衡。
在 customer-provider 中修改 server.port
属性,以此配置文件再次启动一个实例,此时就有两个实例同时提供服务
#spring.application.name 在配置文件中我们配置了应用程序的名称,这个名称很重 要,不能重复。将来调用服务时是使用此名称来调用服务的。 spring: application: name: customer-service #数据库信息 datasource: username: root password: 123456 url: jdbc:mysql:///crm?characterEncoding=utf8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver #设置编码问题 http: encoding: force: true charset: UTF-8 #eureka eureka: client: # eureka.client.service-url.defaultZone 属性配置了注册中心的位置 service-url: defaultZone: http://localhost:8000/eureka #下面两个 默认就是true,可以不写 # register-with-eureka: true # fetch-registry: true server: port: 9001
以从 Eureka中看到如下信息:
客户调用时,两个服务就会实现负载均衡,默认是轮询的策略。下面是eureka负载均衡策略:
策略名 | 命名 | 策略描述 |
---|---|---|
RandomRule | 随机策略 | 随机选择一个server |
RoundRobinRule | 轮询策略 | 按顺序选中server (默认) |
RetryRule | 重试策略 | 在一个配置时间段内,当选择server不成功,则一直尝试选择一个可用的server |
BestAvailableRule | 最低并发策略 | 逐个考察Server,如果Server断路器打开,则忽略,再选择其中并发链接最低的server |
AvailabilityFilteringRule | 可用过滤策略 | 过滤掉那些因为一直连接失败的,被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) |
ResponseTimeWeightedRule | 响应时间加权策略 | 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。响应时间越短,weight越大,被选中的可能性越高。这策略很贴切,综合了各种因素,比如:网络、磁盘、io等,都直接影响响应时间 |
ZoneAvoidanceRule | 区域权重策略 | 综合判断server所在区域的综合性能,和server的可用性,轮询选中server,并且判断一个AWS Zone的运行性能是否可用,剔除不可用Zone中的所有server |
客户端可以配置负载均衡的策略:
customer-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
customer-service
表示作用到哪个微服务, com.netflix.loadbalancer.RandomRule
即随机策略,当然,我们也可以指定为其他策略,包括我们自己定义的,只要把相应的包路径写到这即可,很方便。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。