部署不夠靈活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