1.什么是微服务:
简而言之,微服务微服务架构风格这种开发方式,是以开发一组小型服务的方式来开发一个独立的应用系统。其中每个小型服务都是运行在自己的进程中,并且采用HTTP资源API这样轻量的机制来相互通信。这些服务围绕业务功能进行搭建,并能通过全自动的部署机制来进行独立部署。这些微服务可以使用不同的语言来编写,并且可以使用不同的数据存储技术。对这些微服务我们仅做最低限度的集中管理。(摘自:http://www.martinfowler.com/articles/microservices.html)
2.微服务具备的特征
A.每个微服务都可独立运行在自己的服务进程中;
B.一系列独立运行的微服务共同搭建起整个系统;
C.每个服务为独立的业务开发,一个微服务一般完成某个特定的功能,比如:订单管理,商品管理等;
D.微服务之间通过一些轻量的童鞋机制进行通信,例如:通过REST API或者RPC的方式进行调用。
3.优点
易于开发和维护;启动较快;局部修改容易部署;技术栈不受限;按需伸缩;DevOps
4.挑战
运维要求较高;分布式的复杂性;接口调用成本高;重复劳动
5.设计原则
单一职责原则,服务自治原则,轻量级通信原则,接口明确原则
服务注册中心我需要使用组件上Spring Cloud Netflix的Eureka,eureka只用一个服务注册和发现模块。我们可以将自己定义的API接口注册到Spring Cloud Eureka上,Eureka服务服务的注册与发现。构成Eureka体系包括:服务注册中心、服务提供者、服务消费者。
上图描述了(图片来源于网络):
A.两天Eureka服务注册中构成的注册复制集群;
B.然后服务提供者想注册中心进行注册、续约、下线服务等;
C.服务消费者向Eureka注册中拉去服务列表并维护在本地;
D.然后服务消费者根据从Eureka服务注册中心获取的服务列表选取一个服务提供者进行消费服务。
1.创建一个web-app的maven工程。此处命名为:springcloud;
在该工程下创建module;快速创建一个名为eureka的springboot工程。
勾选Eureka Server。注意springboot版本,建议使用2.0以上版本
2.创建好之后,看下pom.xml是否导入了依赖
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
3.在启动类中加入注解@EnableEurekaServer
package com.springcloud.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @EnableEurekaServer 启动一个服务注册中心提供给其他应用进行对话
* @EnadbleEuredaServe Import导入了EurekaMarkerConfiguration类,eurekaServerMarkerBean会往Spring容器中注入一个空类Marker;
* Marker类是一个开关标志,用了激活EurekaServerAutoConfiguration类。
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
4.将application.properties修改为application.yml,添加配置
server:
port: 8761
spring:
application:
name: eureka
eureka:
instance:
hostname: localhost
client:
register-with-eureka: true #false:即禁止自己注册自己
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #配置服务注册中心访问地址
访问:http://localhost:8761/
可以看到,此时注册中心注册了自己;一般我们都会禁止注册中心注册自己。修改application.yml中register-with-eureka: false即可
1.快速创建一个名为client的springboot工程
我这为了方便测试,加入了myql、mybatis和Web开发相关组件;pom.xml如下
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.7.RELEASE
com.springcloud
client
0.0.1-SNAPSHOT
client
Demo project for Spring Boot
1.8
Greenwich.SR2
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.0
mysql
mysql-connector-java
runtime
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
2.在启动类ClientApplication.java中加入注解@EnableEurekaClient
package com.springcloud.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @EnableEurekaClient 表明自己是一个生产者
*/
@SpringBootApplication
@EnableEurekaClient
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
3.application.yml配置
#配置服务注册中心地址
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: service-client
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/dny_website?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
server:
port: 8765
mybatis:
mapper-locations: classpath:mapping/*Mapper.xml
type-aliases-package: com.springcloud.client.entity
logging:
level:
com:
springcloud:
client:
Dao: debug
项目结构(springboot整合mybatis这里就不细说了,有兴趣的可以看下这篇博客:https://blog.csdn.net/kelly921011/article/details/95475411)
控制层代码:
package com.springcloud.client.Controller;
import com.springcloud.client.entity.Admin;
import com.springcloud.client.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/admin")
public class AdminController {
@Autowired
private AdminService adminService;
@RequestMapping("/list")
public List home(Integer permissions){
return adminService.adminList(permissions);
}
}
4.启动测试
启动服务提供者项目后,查看注册中心
使用postman进行测试:
创建一个名为ribbon的springboot项目。
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.7.RELEASE
com.springcloud
ribbon
0.0.1-SNAPSHOT
ribbon
Demo project for Spring Boot
1.8
Greenwich.SR2
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
2.application.yml配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8762
spring:
application:
name: service-ribbon
3.启动类加入注解@EnableDiscoveryClient
package com.springcloud.ribbon;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class RibbonApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonApplication.class, args);
}
/**
* 加入restTemplate以消费相关的服务。
* @return
*/
@Bean
@LoadBalanced
RestTemplate restTemplate()
{
return new RestTemplate();
}
}
4.创建Service和Contoller
package com.springcloud.ribbon.service;
import com.springcloud.customer.entity.Admin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.List;
@Service
public class RibbonService {
@Autowired
private RestTemplate restTemplate;
public String StringServcie(){
return restTemplate.getForObject("http://SERVICE-CLIENT/admin/string",String.class);
}
public List ListService(Integer permissions){
/**
* 方法getForObject(url,?.class)中的url必须使用服务提供者的项目名称“CLIENT”,不能使用IP地址
* RestTemplate接收List集合数据时,必须用数组接收
*/
Admin[] admin=restTemplate.getForObject("http://SERVICE-CLIENT/admin/list?permissions="+permissions,Admin[].class);
for(Admin a:admin){
System.out.println(a.getAdmin_name());
}
List list= Arrays.asList(admin);
return list;
}
}
package com.springcloud.ribbon.controller;
import com.springcloud.customer.entity.Admin;
import com.springcloud.customer.service.RibbonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/ribbon")
public class RibbonController {
@Autowired
private RibbonService testService;
@RequestMapping("/string")
public String findString(){
return testService.StringServcie();
}
@RequestMapping("/list")
public List AdminList(Integer permissions){
return testService.ListService(permissions);
}
}
测试:
创建项目,导入依赖;pom.xml:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.8.RELEASE
com.springcloud
customer
0.0.1-SNAPSHOT
customer
Demo project for Spring Boot
1.8
Greenwich.SR2
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
application.yml
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8764
spring:
application:
name: service-feign
#feign的配置,连接超时及读取超时配置
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: basic
主类CustomerApplication:
package com.springcloud.customer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @EnableDiscoveryClient 声明自己是一个服务消费者
* @EnableFeignClients 启用feign客户端
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class CustomerApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerApplication.class, args);
}
}
创建Service和Controller:
package com.springcloud.customer.service;
import com.springcloud.customer.entity.Admin;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
* feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。Spring Cloud集成了Ribbon和Eureka,
* 可在使用Feign时提供负载均衡的http客户端。
*/
@FeignClient(value = "service-client")
public interface FeignService {
@RequestMapping("/admin/string")
public String StringService();
@PostMapping("/admin/list")
public List FeignList(@RequestParam("permissions")Integer permissions);
}
package com.springcloud.customer.controller;
import com.springcloud.customer.entity.Admin;
import com.springcloud.customer.service.FeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/feign")
public class FeignController {
@Autowired
private FeignService feignService;
@RequestMapping("/string")
public String FeignString(){
return feignService.StringService();
}
@RequestMapping("/list")
public List FeignList(Integer permissions){
return feignService.FeignList(permissions);
}
}
SpringCloud搭建(下)------断路器(Netflix Hystrix)+网关(Netflix Zuul)+配置中心(Spring Cloud Config)