部署不够灵活html
定义:支持应用程序和服务的开发,能够利用物理架构和多个自制的处理元素(多节点),不共享主内存,但经过网络发送消息前端
网关功能,控制流量,监控和日志java
把两个接口聚合在一块儿返回出去mysql
经过不一样需求返回不一样数据,pc和手机端淘宝返回详情数据不一致git
Dubboweb
Zookeeperajax
Spring MVC or SpringBootspring
基于Netflix Eureka作了二次封装sql
http://projects.spring.io/spr...docker
版本查看
-Dserver.port=
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
eureka: client: service-url: defaultZone: http://localhost:8080/eureka/ # 不把本身注册到注册中心 register-with-eureka: false # 设置应用名 spring: application: name: eureka
mvn clean package install
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ # 不把本身注册到注册中心 register-with-eureka: false #关闭心跳监测 server: enable-self-preservation: false # 设置应用名 spring: application: name: eureka server: port: 8761
@EnableDiscoveryClient
和@EnableEurekaClient
区别若是注册中心是eureka那么推荐使用EnableEurekaClient`
若是是其余注册中心那么推荐使用Enable
两个eureka都能看到client的信息
若是一个client挂掉了那么两个eureka都没有信息
解决:
多台
a和b沟通彻底经过注册中心
任何组织在设计一套系统时,所交互的设计方案在结构上都与该组织的沟通结构保持一直
Y轴功能解耦
关注点分离
通用性分离
粒度分离
依据服务特色选择不一样结构的数据库类型
难点在难以肯定边界
直接使用RestTemplate
String s = restTemplate.getForObject("http://localhost:8083/hello", String.class);
使用LoadbalanceClient
ServiceInstance serviceInstance = loadBalancerClient.choose("PRODUCT"); String url = String.format("http://%s:%s", serviceInstance.getHost(), serviceInstance.getPort() + "/hello"); String result = restTemplate.getForObject(url, String.class);
使用注解
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }
轮循策略默认是roundRobinRule
http://cloud.spring.io/spring...
users: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
Pom文件
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
@FeignClient
编写接口
@FeignClient("product") public interface FeignConfig { @GetMapping("hello") String hello(); }
注入和调用
@Autowired private FeignConfig feignConfig; @RequestMapping("/feign") public String feign() { String result = feignConfig.hello(); return result; }
product-server
product-client
Product-common
依赖关系
mvn -Dmaven.test.skip=true -U clean install
商品服务库存变化发布消息,订单服务订阅消息,好比商品信息
常见消息队列
5672->默认RabbitMQServer端口
15672->RabbitMQ管理页面端口,页面只须要配置这个
docker run -d --hostname my-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3.7.3-management
默认密码:guest
configServer从远端git拉下配置放到本地git若是远端不可用使用本地的
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
开启注解
@EnableDiscoveryClient @EnableConfigServer
在git上新建项目
访问对应配置文件
/{label}/{name}-{profiles}
设置配置文件基础目录
spring.cloud.config.server.git.basedir
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-client</artifactId> </dependency>
spring: application: name: order cloud: config: discovery: enabled: true service-id: config profile: dev
修改成bootstrap.yml这样会优先启动
配置中心会读取拼接order.yml+order-xx.yml的内容
经过git hook访问配置文件变动,同步信息到消息队列,(/bus/refresh)
Config-server 经过消息队列同步到其余服务
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.BUILD-SNAPSHOT</version> <relativePath/> <!-- lookup parent from repository --> </parent> <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.BUILD-SNAPSHOT</spring-cloud.version> </properties>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> <version>2.0.0.RELEASE</version> </dependency>
management: endpoints: web: exposure: include: bus-refresh
curl -v -X POST "http://localhost:8991/actuator/bus-refresh"
@RefreshScope
@RestController @RequestMapping("/env") @RefreshScope public class EnvController { @Value("${env}") public String env; @GetMapping("/profile") public String getenv() { return env; } }
异步:客户端请求不会阻塞进程,服务端的响应能够是非及时的
经过消息实现一对多
异步处理
流量削锋
日志处理(kafka)
应用解耦
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
spring: application: name: order cloud: config: discovery: enabled: true service-id: config profile: test rabbitmq: host: localhost port: 5672 username: guest guest: guest
@Autowired private AmqpTemplate amqpTemplate; @Test public void send() { amqpTemplate.convertAndSend("myQueue", "now time:" + System.currentTimeMillis()); }
@Slf4j @Component public class MqReceiver { @RabbitListener(queues = "myQueue") public void process(String message) { log.info("MqReceiver:{}", message); } }
/** * 自动建立队列 * * @param message */ @RabbitListener(queuesToDeclare = @Queue("myQueue2")) public void autoCreateQueue(String message) { log.info("autoCreateQueue:{}", message); }
第三种 Exchange和Queue绑定
@RabbitListener(bindings = {@QueueBinding( value = @Queue("myQueueExchange"), exchange = @Exchange("myExchange") )}) public void exchange(String message) { log.info("myExchange:{}", message); }
消息分组使用第三种方式
@RabbitListener(bindings = @QueueBinding( exchange = @Exchange("myOrder"), key = "computer", value = @Queue("computerOrder") )) public void computerOrder(String message) { log.info("computerOrder:{}", message); } @RabbitListener(bindings = @QueueBinding( exchange = @Exchange("myOrder"), key = "fruit", value = @Queue("fruitOrder") )) public void fruitOrder(String message) { log.info("fruitOrder:{}", message); }
@Test public void sendToProduct() { amqpTemplate.convertAndSend("myOrder", "computer", "now time:" + System.currentTimeMillis()); }
为微服务应用构建消息能力的应用,对于消息中间件的封装,代码对于中间件的无感知,可是只支持rabbitMQ 和Kafka
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-stream-rabbit</artifactId> </dependency>
public interface StreamClient { @Input("myMessage") SubscribableChannel input(); @Output("myMessage") MessageChannel output(); }
@Component @EnableBinding(StreamClient.class) @Slf4j public class StreamReceiver { @StreamListener("myMessage") public void process(Object message) { log.info("StreamReceiver:{}",message); } }
@RestController public class SendMessageController { @Autowired private StreamClient streamClient; @GetMapping("/sendMessage") public void process() { String message = "now " + new Date(); streamClient.output().send(MessageBuilder.withPayload(message).build()); } }
参考:https://coding.imooc.com/learn/list/187.html