Mega-Wechat은 Swoole 네트워크 프레임워크를 기반으로 구현된 WeChat 템플릿 메시지를 보내는 서비스입니다. 대량의 메시지 전송을 지원하고 전송 템플릿 메시지 인터페이스를 동시에 실행합니다. 전체 전송 프로세스는 선착순으로 대기열에 따라 실행됩니다. 언제든지 변경하여 사용할 수 있는 맞춤형 템플릿 메시지를 지원합니다.
회사에서 운영할 때 지정된 사용자에게 위챗 템플릿 메시지를 자주 보내야 하는 경우에는 다른 사업의 구현이 더 시급하기 때문에 단순히 일부 템플릿 메시지를 컨트롤러에 하드코딩하고 실행하면 됩니다. 사용 시 작업 요구 사항을 완료하는 명령입니다. 따라서 템플릿 내용을 변경할 때 코드를 변경하고 git으로 업데이트해야 합니다. 게다가 단일 프로세스의 문제로 인해 많은 수의 템플릿 메시지를 보내는 것은 매우 시간이 많이 걸립니다(주로 시간이 많이 소요되기 때문에). WeChat 인터페이스를 호출하는 데 시간이 소요됨).
이에 대해 몇 가지 솔루션이 떠올랐습니다.
첫 번째 방법은 다중 프로세스 클라이언트를 직접 구현하여 WeChat을 호출하여 컬을 통해 템플릿 메시지 API를 보냅니다. 이 방법은 구현이 간단하고 빠르지만, 템플릿 메시지를 호출하는 다른 비즈니스의 요구 사항을 지원할 수는 없습니다.
두 번째 방법은 하나의 프로세스가 작업을 분산시키고 여러 하위 프로세스를 분기하고 하위 프로세스를 통해 Redis 대기열을 지속적으로 폴링하도록 하는 것입니다. 이 솔루션도 구현하기가 비교적 간단하지만 제어 가능성이 너무 낮아 기본적으로 제어하기가 어렵습니다.
세 번째이자 현재 사용되는 솔루션은 swoole을 통해 메시지 대기열과 유사한 서비스를 구현하는 것입니다. 여러 작업이 느린 컬 작업을 수행하여 WeChat API를 조정하고 실행 결과를 클라이언트에 반환할 수 있습니다. swoole은 매우 강력한 네트워크 프레임워크이며 많은 동시성을 받을 수 있으므로 이론상으로 swoole은 템플릿 메시지 전송에 대한 많은 수의 요청을 처리할 수 있습니다. 그러나 WeChat의 템플릿 메시지 전송 API는 상대적으로 시간이 많이 걸리기 때문에 많은 수의 요청이 처리됩니다. 배달 요청하기 때문에 작업에서 실행 처리 속도가 수신 속도만큼 빠르지 않아 버퍼 오버플로가 발생하므로 Mega-Wechat은 작업 프로세스가 유휴 상태일 때 모든 요청을 먼저 대기열에 넣기 위해 파일 대기열을 사용합니다. 템플릿 메시지 전송 요청을 처리하는 작업으로 이동합니다. 이러한 구현은 버퍼 오버플로를 일으키지 않으며 많은 양의 동시성을 지원할 수 있습니다. 그러나 WeChat에는 템플릿 메시지에 대한 일련의 규칙과 제한 사항이 있으므로 많은 API 호출은 단지 이론적인 것입니다.
Mega-Wechat 시스템 아키텍처는 아래 그림에 나와 있습니다.
시스템 실행 프로세스 설명:
위의 설명은 동기식 프로세스이며 클라이언트에 대한 비동기식 또는 동기식 처리일 수 있습니다.
config/ 服务器配置
libs/
Network/
Server/
Swoole/ Mega核心类库
Wechat/ 微信API
logs/
vendor/ 支持composer,依赖monolog写日志
autoload.php
mega Mega命令入口
첫 번째 단계 PHP를 설치하려면 버전 5.6 이상이 필요합니다. 서버 측 대기열은 SPL 기능과 PHP의 새로운 기능 구문을 사용하기 때문에
2단계 MySQL을 설치하면 어떤 버전이든 괜찮습니다.
냠 mysql을 설치해봐
설치가 성공적으로 완료되면 MySQL은 mega_wechat_template 테이블을 생성해야 합니다. 자세한 구조는 다음 장에서 소개됩니다.
3단계 Swoole 확장을 설치하기 전에 다음 소프트웨어가 시스템에 설치되어 있는지 확인해야 합니다.
php-5.3.10 이상 gcc-4.4 이상 make autoconf
주소 다운로드
https://github.com/swoole/swoole-src/releases
http://pecl.php.net/package/swoole
http://git.oschina.net/matyhtf/swoole
소스코드 패키지를 다운로드한 후 터미널에 소스코드 디렉터리에 입력하고 다음 명령어를 실행하여 컴파일 및 설치합니다.
CD 스울
PHPize ./구성
만들다
설치하다
WeChat 템플릿은 Mega-Wechat 서버에 저장됩니다. 이는 대부분의 기업이 템플릿의 내용을 자주 수정해야 하기 때문입니다. 자주 변경해야 하는 이러한 템플릿의 경우 프로그램에 작성하는 것이 매우 불편합니다. 따라서 템플릿을 저장하고 몇 가지 추가 필드를 추가하는 데 MySql이 사용됩니다. 비즈니스에서 요구합니다.
서버의 경우 데이터베이스 템플릿이 시작될 때 캐시됩니다. 템플릿을 업데이트해야 하는 경우 서버의 템플릿 캐시를 실시간으로 업데이트하는 해당 명령이 있으므로 가져올 필요가 없습니다. 템플릿이 전송될 때마다 데이터베이스에서 템플릿이 삭제되어 성능 저하 문제가 발생합니다.
테이블 구조:
CREATE TABLE ` mega_wechat_template ` (
` tmpl_key ` char ( 32 ) NOT NULL COMMENT '模板key ' ,
` title ` varchar ( 100 ) NOT NULL DEFAULT ' ' COMMENT '模板标题' ,
` template ` text NOT NULL COMMENT '模板内容' ,
` created_at ` int ( 11 ) NOT NULL DEFAULT ' 0 ' ,
` updated_at ` int ( 11 ) NOT NULL DEFAULT ' 0 ' ,
PRIMARY KEY ( ` tmpl_key ` )
)
필드 설명:
필드 | 설명하다 |
---|---|
tmpl_key | 템플릿 키(메가 템플릿 명령 요청을 전송하기 위한 매개변수) |
제목 | 템플릿 제목 |
주형 | 템플릿 콘텐츠, 저장 형식은 json입니다. |
생성_시간 | 생성 시간 |
업데이트_시간 | 업데이트 시간 |
template字段格式,例子如下:
{
"touser" : " ${OPENID} " ,
"template_id" : " ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY " ,
"url" : " http://weixin.qq.com/download " ,
"data" :{
"first" : {
"value" : "恭喜你购买成功! " ,
"color" : " #173177 "
},
"keynote1" :{
"value" : "巧克力" ,
"color" : " #173177 "
},
"keynote2" : {
"value" : " 39.8元" ,
"color" : " #173177 "
},
"keynote3" : {
"value" : " 2014年9月22日" ,
"color" : " #173177 "
},
"remark" :{
"value" : "欢迎再次购买! " ,
"color" : " #173177 "
}
}
}
注意:JSON中的${OPENID},是自定义的变量,调用微信模板消息接口前会先解析json模板并替换相应的自定义变量。
该变量由发送Mega模板命令请求的参数定义
구성 파일은 config 디렉터리에 균일하게 배치되며 각 서버는 독립적인 구성을 갖습니다.
[server]
;启动server类
class = " ServerMegaWechatServer "
;协议类
protocol = " NetworkMegaWechatProtocol "
;主机和端口
listen[] = 127.0.0.1:9501
;缓存模板个数
table_size = 100 ;
;缓存模板内容最大size
template_size = 4048
;文件队列存储路径
queue_file_path = " /Mega-Wechat/logs/queue "
[setting]
; ;;;;;;;;;;;swoole配置;;;;;;;;;;;;;;
dispatch_mode = 2
worker_num = 2
task_worker_num = 8
open_eof_check = true
package_length_type = N
package_length_offset = 0
package_body_offset = 4
package_max_length = 2465792
daemonize = 1
; ;swoole_log文件
; log_file = "/qcloud/logs/swoole.log"
[pdo]
dsn = " mysql:host=127.0.0.1;dbname=mega "
username = root
password = i201314
table_prefix = mega_
[wechat]
app_id = wx10c4b54cf0aae125
app_secret = e01207cc547f62d73f5099aae83a9f15
token = e01207cd547f62d73f5099cae83a9f15
[log]
; ;;;;;系统log配置,基于monolog;;;;;;
log_file = /Mega-Wechat/logs/mega.log
;存储日志级别
log_level = warning
;日志前缀
log_prefix = mega
각 .ini 파일을 서비스 이름 및 구성(예: config/wechat.ini 구성 파일)으로 사용하여 구성 파일에 따라 서버를 시작합니다.
cd Mega-Wechat
//php mega ${配置文件名} ${cmd}
php mega wechat start //开启服务
php mega wechat stop //关闭服务
php mega wechat restart //重启服务
Mega-Wechat은 TCP를 사용하여 통신하며 프로토콜은 고정 헤더 + 패킷 본문 프로토콜 설계를 채택합니다. 일반적인 프로토콜 형식은 다음과 같습니다.
{packLength}{headerLength}{command} {params}{opaque}{bodyLength}{body}
참고: {command} {params} 사이의 공백, 각 params 매개변수는 공백으로 구분됩니다.
템플릿 메시지 명령 프로토콜 보내기, 각 명령은 WeChat 템플릿 메시지 전송을 나타냅니다. 클라이언트는 서버에 Send 명령을 보냅니다. 그러면 WeChat 템플릿 메시지 API가 한 번 실행되고 그 결과로 클라이언트에 응답하고 ACK 확인이 반환됩니다.
해당 클래스는 NetworkSendCommand입니다.
/**
* @param $opaque int 发送序号
* @param $openid string 微信openid
* @param $key string 模板key
* @param $data array 自定义变量,可选,默认为null,例子如下:
* 传入数组为:['mega' => 'wechat']
* 模板内容中包含一个${mega}自定义变量,则数组中的mega值会替换到相应变量中。
* @param $fd int 客户端标志,可选,默认为null
*/
new SendCommand ( $ opaque , $ openid , $ key , $ data , $ fd )
템플릿 메시지 대기열에 넣는 명령 프로토콜입니다. 명령을 받은 후 서버는 즉시 대기열에 합류하고 ACK 확인으로 응답합니다. 이후 대기열에 따라 대기한 후 WeChat 템플릿 메시지 처리를 실행합니다.
해당 클래스는 NetworkPushCommand입니다.
/**
* @param $opaque int 发送序号
* @param $openid string 微信openid
* @param $key string 模板key
* @param $data array 自定义变量,可选
*/
new PushCommand ( $ opaque , $ openid , $ key , $ data )
템플릿 캐싱 명령 프로토콜을 설정합니다. 이 명령을 받은 후 서버는 키에 따라 데이터베이스에서 템플릿 콘텐츠를 가져와 메모리에 캐시합니다. 키가 존재하지 않거나 캐시 크기를 초과하면 관련 오류 메시지로 응답합니다.
해당 클래스는 NetworkSetTableCommand입니다.
/**
* @param $opaque int 发送序号
* @param $key string 模板key
* @param $fd int 客户端标志,客户端发送命令时可为null
*/
new SetTableCommand ( $ opaque , $ key , $ fd )
일반 응답 명령 프로토콜, 요청 결과를 반환합니다. 이 프로토콜은 ACK 확인 및 반환된 불투명 값을 기반으로 한 마지막 요청에 대한 응답으로 사용될 수 있습니다. 반환된 코드는 HTTP 프로토콜 응답 상태 코드와 동일한 의미를 사용하여 응답 코드로 사용됩니다. 응답이 오류인 경우 일반적으로 메시지 필드가 포함됩니다. 예를 들어 보내기 명령이 전송되지 않으면 응답 코드는 400이 되고 메시지는 WeChat 템플릿 메시지 인터페이스에서 응답으로 반환되는 json이 됩니다.
해당 클래스는 NetworkBooleanCommand입니다.
/**
* @param $code int 应答状态码
* @param $message string 消息内容
* @param $opaque int 应答序号
*/
new BooleanCommand ( $ code , $ message , $ opaque )
첫 번째는 Send 프로토콜을 사용하는 것이고, 다른 하나는 Push 프로토콜을 사용하는 것입니다. 둘 다 서로 다른 시나리오에 대처할 수 있습니다.
푸시 프로토콜은 주로 WeChat이 API를 호출할 때까지 기다리지 않으려는 구현에 사용됩니다. 구체적으로 Push는 각 템플릿 메시지를 대기열에 넣고 서버는 즉시 응답합니다. 이때 클라이언트는 템플릿 메시지의 성공 여부에 신경 쓰지 않고 비즈니스 로직을 계속 실행할 수 있습니다. (서버 측은 이 메시지를 소비한다는 것을 보장할 수 있습니다)
Send 프로토콜은 푸시와 달리 템플릿 메시지도 보냅니다. 서버는 WeChat 템플릿 메시지 API를 호출한 후 결과로 응답합니다. 응답을 받은 후 클라이언트는 전송된 결과를 얻을 수 있습니다(응답은 결과 프로토콜, 성공하면 반환된 코드는 200, 실패하면 코드 400이 반환되고 메시지는 WeChat에서 반환한 결과의 json입니다). .결과에 따라 클라이언트는 해당 업무를 수행할 수 있습니다.
Send 프로토콜에는 몇 가지 문제가 있습니다.
위의 문제에 비해 이 프로토콜의 장점은 전송 결과를 알 수 있고 다음 메시지를 계속 보낼지 여부에 대한 비즈니스 로직을 제어할 수 있다는 것입니다.
실제 시나리오: 지정된 사용자 그룹 또는 모든 사용자에게 일괄적으로 템플릿 메시지를 보내야 하는 경우 이 프로토콜을 사용하여 이를 달성할 수 있습니다. 사용자에게 일괄 템플릿 메시지를 보내는 것은 작업으로 간주될 수 있습니다. 작업에는 전송된 메시지 수, 성공 횟수, 실패 횟수, 템플릿 키 등과 같은 데이터가 포함됩니다. 전송 프로세스를 보내고 받고 기록하는 비즈니스 로직은 클라이언트를 통해 구현됩니다. 각 서버 응답은 업데이트 성공 또는 실패의 기준으로 사용됩니다. 구체적인 업무 프로세스는 다음과 같습니다.
위의 비즈니스 로직을 구현하려면 Swoole 비동기 클라이언트를 사용하는 것이 좋습니다. 실행 후 클라이언트는 완료해야 할 때 데몬 프로세스로 백그라운드에서 실행될 수 있습니다.
클라이언트 구현 렌더링이 첨부되어 있습니다.
마지막으로 오픈 소스 클라이언트 DEMO github이 첨부됩니다: https://github.com/imRainChen/Mega-WeChat-Client
제안사항이 있으시면 언제든지 저희에게 연락해 주세요. 질문과 피드백을 게시하실 수도 있습니다.
이메일: [email protected]
Apache 라이센스 버전 2.0은 http://www.apache.org/licenses/LICENSE-2.0.html을 참조하세요.